Skip to content

Instantly share code, notes, and snippets.

@haskellcamargo
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haskellcamargo/2941bb4cd9b217439f9b to your computer and use it in GitHub Desktop.
Save haskellcamargo/2941bb4cd9b217439f9b to your computer and use it in GitHub Desktop.
Harbour Prelude
/**
* This file is responsible by the preprocessor definitions and macros for
* work on syntax.
* @lastmod: 2015-03-13
* @author : Marcelo Haskell Camargo
*/
// Range syntax: @{ nStart .. nEnd }
#xtranslate @{ <nStart> .. <nEnd> } => Z_Range( <nStart>, <nEnd> );
// Range syntax with step: @{ nStart, nNext .. nEnd }
#xtranslate @{ <nStart>, <nNext> .. <nEnd> } => ;
Z_StepRange( <nStart>, <nEnd>, <nNext> )
// Specify Prelude functions to not affect the whole system, following the same
// principles of Protheus user's functions.
#xtranslate Prelude Function <cNome> => Function Z_<cNome>
#xtranslate @<cName> { <arg1> } => Z_<cName>( <arg1> )
#xtranslate @<cName> { <arg1>, <arg2> } => Z_<cName>( <arg1>, <arg2> )
#xtranslate @<cName> { <arg1>, <arg2>, <arg3> } => ;
Z_<cName>( <arg1>, <arg2>, <arg3> )
// Special notation for calls
#xtranslate @<cName> <cList> ::= <expr> => ;
Z_<cName>( <expr>, <cList> )
// <func> Of <list>
#xtranslate @<cName> <expr> Of <aList> => ;
Z_<cName>( <expr>, <aList> )
// Binding, like Haskell
#xtranslate <cF> >>= <cG> In <expr> => <cF>( <cG>( <expr> ) )
// Syntactic sugar for aAdd
#xtranslate <cVar>\[\] := <expr> => aAdd( <cVar>, <expr> )
/**
* A port of Haskell's/Livescript's Prelude library
* for handling lists and data
* @lastmod: 2015-03-13
* @author : Marcelo Haskell Camargo
*/
// #include "PreludeSyntax.ch"
/**
* +=====================+
* | List Handling |
* +=====================+
*/
Prelude Function Range( nStart, nEnd )
Local aAccum := { } ;
, nI
For nI := nStart To nEnd
aAdd( aAccum, nI )
Next nI
Return aAccum
Prelude Function StepRange( nStart, nEnd, nNext )
Local aAccum := { } ;
, nI
For nI := nStart To nEnd Step (nNext - nStart)
aAdd( aAccum, nI )
Next nI
Return aAccum
/**
* Applies a function to each item in the list, and produces a new list with
* the results. The length of the result is the same
* length as the input.
* @param : bBlock :: Block
* @param : aList :: Array
* @type : (a -> b) -> [a] -> [b]
* @return : Array
* @test : Pass
*/
Prelude Function Map( bBlock, aList )
Local aAccum := Array( Len( aList ) ) ;
, nI
For nI := 1 To Len( aList )
aAccum[ nI ] := Eval( bBlock, aList[ nI ] )
Next nI
Return aAccum
/**
* Applies a function to each item in the list and returns the original list.
* Used for side effects.
* @param : bBlock :: Block
* @param : aList :: Array
* @type : (a -> Undefined) -> [a] -> [a]
* @return : Array
* @test : Pass
*/
Prelude Function Each ( bBlock, aList )
Local nI
For nI := 1 To Len( aList )
Eval( bBlock, aList[ nI ] )
Next nI
/**
* Returns a new list which contains only the truthy values of the inputted
* list.
* @param : aList :: Array
* @type : [a] -> [a]
* @return : Array
* @test : Pass
*/
Prelude Function Compact( aList )
Local aAccum := { } ;
, nI
For nI := 1 To Len( aList )
If aList[ nI ]
aAdd( aAccum, aList[ nI ] )
EndIf
Next nI
Return aAccum
/**
* Returns a new list composed of the items which pass the supplied function's
* test.
* @param : bBlock :: Block
* @param : aList :: Array
* @type : (a -> Boolean) -> [a] -> [a]
* @return : Array
* @test : Pass
*/
Prelude Function Filter( bBlock, aList )
Local aAccum := { } ;
, nI
For nI := 1 To Len ( aList )
If Eval( bBlock, aList[ nI ] )
aAdd( aAccum, aList[ nI ] )
EndIf
Next nI
Return aAccum
/**
* Like filter, but the new list is composed of all the items which fail the
* function's test.
* @param : bBlock :: Block
* @param : aList :: Array
* @type : (a -> Boolean) -> [a] -> [a]
* @return : Array
* @test : Pass
*/
Prelude Function Reject( bBlock, aList )
Local aAccum := { } ;
, nI
For nI := 1 To Len ( aList )
If !Eval( bBlock, aList[ nI ] )
aAdd( aAccum, aList[ nI ] )
EndIf
Next nI
Return aAccum
/**
* Equivalent to [(filter f, xs), (reject f, xs)], but more efficient, using
* only one loop.
* @param : bBlock :: Block
* @param : aList :: Array
* @type : (a -> Boolean) -> [a] -> [[a], [a]]
* @return : Array
* @test : Pass
*/
Prelude Function Partition( bBlock, aList )
Local aAccum := { { }, { } } ;
, nI
For nI := 1 To Len( aList )
If Eval( bBlock, aList[ nI ] )
aAdd( aAccum[ 1 ], aList[ nI ] )
Else
aAdd( aAccum[ 2 ], aList[ nI ] )
EndIf
Next nI
Return aAccum
/**
* Equivalent to [(filter f, xs), (reject f, xs)], but more efficient, using
* only one loop.
* @param : bBlock :: Block
* @param : aList :: Array
* @type : (a -> Boolean) -> [a] -> Maybe a
* @return : xItem
* @test : Pass
*/
Prelude Function Find( bBlock, aList )
Local nI
For nI := 1 To Len( aList )
If Eval( bBlock, aList[ nI ] )
Return aList[ nI ]
EndIf
Next nI
Return Nil
/**
* The first item of the list. Returns undefined if the list is empty.
* @param : aList :: Array
* @type : [a] -> Maybe a
* @return : xItem
* @test : Pass
*/
Prelude Function Head( aList )
Return aList[ 1 ]
/**
* Everything but the first item of the list.
* @param : aList :: Array
* @type : [a] -> [a]
* @return : Array
* @test : Pass
*/
Prelude Function Tail( aList )
Return aDel( aList, 1 )
/**
* Everything but the last item of the list.
* @param : aList :: Array
* @type : [a] -> [a]
* @return : Array
* @test : Pass
*/
Prelude Function Initial( aList )
Local aAccum := Array( Len( aList ) - 1 ) ;
, nI
For nI := 1 To ( Len( aList ) - 1 )
aAccum[ nI ] := aList[ nI ]
Next nI
Return aAccum
/**
* Returns a new list which is the reverse of the inputted one.
* @param : aList :: Array
* @type : [a] -> [a]
* @return : Array
* @test : Pass
*/
Prelude Function Reverse( aList )
Local aAccum := { } ;
, nI
For nI := Len( aList ) To 1 Step -1
aAdd( aAccum, aList[ nI ] )
Next nI
Return aAccum
/**
* Concatenates a list of lists together.
* @param : aList :: Array
* @type : [[a]] -> [a]
* @return : Array
* @test : Pass
*/
Prelude Function Concat( aList )
Local aAccum := { } ;
, nI, nJ
For nI := 1 To Len( aList )
For nJ := 1 To Len( aList[ nI ] )
aAdd( aAccum, aList[ nI ][ nJ ] )
Next nJ
Next nI
Return aAccum
/**
* Returns false if any item in the list is false, otherwise returns true.
* @param : aList :: Array
* @type : [a] -> Bool
* @return : Logic
* @test : Fail
*/
Prelude Function AndList( aList )
Local nI
For nI := 1 To Len( aList )
If !aList[ nI ]
Return .F.
EndIf
Next nI
Return .T.
Prelude Function OrList( aList )
Local nI
For nI := 1 To Len( aList )
If aList[ nI ]
Return .T.
EndIf
Next nI
Return .F.
Prelude Function Any( bBlock, aList )
Local nI
For nI := 1 To Len( aList )
If Eval( bBlock, aList[ nI ] )
Return .T.
EndIf
Next nI
Return .F.
Prelude Function All( aList )
Local nI
For nI := 1 To Len( aList )
If !aList[ nI ]
Return .F.
EndIf
Next nI
Return .T.
Prelude Function Sort( aList )
Return aSort( aList )
Prelude Function Sum( aList )
Local nSum := 0 ;
, nI
For nI := 1 To Len( aList )
nSum += aList[ nI ]
Next nI
Return nSum
Prelude Function Product( aList )
Local nProd := 1 ;
, nI
For nI := 1 To Len( aList )
nProd *= aList[ nI ]
Next nI
Return nProd
Prelude Function Mean( aList )
Local nSum := 0 ;
, nI
For nI := 1 To Len( aList )
nSum += aList[ nI ]
Next nI
Return nSum / Len( aList )
Prelude Function Maximum( aList )
Local nMax := aList[ 1 ] ;
, nI
For nI := 1 To Len( aList )
If aList[ nI ] > nMax
nMax := aList[ nI ]
EndIf
Next nI
Return nMax
Prelude Function Minimum( aList )
Local nMin := aList[ 1 ] ;
, nI
For nI := 1 To Len( aList )
If aList[ nI ] < nMin
nMin := aList[ nI ]
EndIf
Next nI
Return nMin
Prelude Function Slice( nX, nY, aList )
Local aAccum := { } ;
, nI
For nI := nX To nY
aAdd( aAccum, aList[ nI ] )
Next nI
Return aAccum
Prelude Function Take( nX, aList )
Local aAccum := Array( nX ) ;
, nI
For nI := 1 To nX
aAccum[ nI ] := aList[ nI ]
Next nI
Return aAccum
Prelude Function TakeWhile( bBlock, aList )
Local aAccum := { } ;
, nI
For nI := 1 To Len( aList )
If !Eval( bBlock, aList[ nI ] )
Return aAccum
Else
aAdd( aAccum, aList[ nI ] )
EndIf
Next nI
Return aAccum
Prelude Function Zip( aA, aB )
Local aAccum := { } ;
, nI
For nI := 1 To Len( aA )
aAdd( aAccum, { aA[ nI ], aB[ nI ] } )
Next nI
Return aAccum
Prelude Function ZipWith( bBlock, aA, aB )
Local aAccum := { } ;
, nI
For nI := 1 To Len( aA )
aAdd( aAccum, Eval( bBlock, aA[ nI ], aB[ nI ] ) )
Next nI
Return aAccum
Prelude Function ElemIndex( xElem, aList )
Local nI
For nI := 1 To Len( aList )
If aList[ nI ] == xElem
Return nI
EndIf
Next nI
Return Nil
Prelude Function ElemIndices( xElem, aList )
Local aAccum := { } ;
, nI
For nI := 1 To Len( aList )
If aList[ nI ] == xElem
aAdd( aAccum, nI )
EndIf
Next nI
Return aAccum
Prelude Function FindIndex( bBlock, aList )
Local nI
For nI := 1 To Len( aList )
If Eval( bBlock, aList[ nI ] )
Return nI
EndIf
Next nI
Return Nil
Prelude Function FindIndices( bBlock, aList )
Local aAccum := { } ;
, nI
For nI := 1 To Len( aList )
If Eval( bBlock, aList[ nI ] )
aAdd( aAccum, nI )
EndIf
Next nI
Return aAccum
Prelude Function Negate( nI )
Return -( nI )
Prelude Function SigNum( nI )
If nI > 0
Return 1
ElseIf nI < 0
Return -1
EndIf
Return 0
@haskellcamargo
Copy link
Author

First class blocks rule!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment