Package com.singularsys.extensions.lambda

Anonymous lambda functions and higher order functions.

Anonymous functions can be defined using the syntax x=>x^2 or [x,y]=>x+y and assigned to variable Square = x=>x^2. Various higher order functions take these as arguments

  • map applies the function to each element of a list and returns a list. For example map(x=>x^2,[1,2,3,4,5]) produces a set of squares.
  • apply applies the function once. For example apply([x,y]=>x^y,5,2)
  • fold combines the elements of a sequence. It takes a two argument lambda function, an applies it to first two elements of the sequence, it then applies the function to the result and the third element. A sum of elements is simply fold([x,y]=>x+y,[1,2,3,4,5]).
  • sort sorts a sequence. For example sort([x,y]=>x - y,[3,2,7,6,8])
  • filter applies a filter to a list, returns the elements which meet a condition. For example filter(x=>x%2==0,[1,2,3,4,5])
  • merge merge two sequences element by element. For example merge([x,y]=>x^y,[1,2,3,4,5],[2,2,2,2,2])
  • iterate generate a sequence. For example iterate(first_value, n=>n+2, n=>n<100)
  • define turns a lambda function into a regular function. define("sq",x=>x^2); sq(5).

The package also defines a range function and operator which generates a sequence [1..10].

To setup first the operators for range, and lambda functions should be added. The ternary cond ? x : y is also useful to add.

OperatorTable2 optab = new StandardOperatorTable2();
                
Operator rangeOp = new RangeOperator("..", "[", "]", new Range(), Operator.BINARY+Operator.NOT_IN_PARSER);
optab.insertOperator(new OperatorKey(){}, rangeOp, optab.getAssign());
                
TernaryOperator ternOp = new TernaryOperator("cond", "?", ":", 
                new TernaryConditional(), 
                Operator.TERNARY+Operator.NARY+Operator.LEFT);
optab.insertOperator(new OperatorKey(){}, ternOp,optab.getAssign());
                
Operator lambdaOp = new Operator("=>", new LambdaFunGenerator(), Operator.BINARY);
optab.insertOperator(new OperatorKey(){}, lambdaOp, optab.getAssign());
The lambdaOperator should be added with a precedence just less than the assignment operator and greater than all other operators.

To use the range operator a modified configurable parser must be use. This adds a new symbol (.. by default) to the parser and adds a new GrammarMatcher. If .. is used then care needs is needed that notation is not confuse with the dots in numbers or the . operator used for dot products.

ConfigurableParser cp = new ConfigurableParser();
cp.addHashComments();
cp.addSlashComments();
cp.addSingleQuoteStrings();
cp.addDoubleQuoteStrings();
cp.addWhiteSpace();
cp.addTokenMatcher(  // enhanced regexp ensuring 1..2 is not parsed as 1. .2
        new NumberTokenMatcher("((\\d+\\.\\d+)|(\\d+\\.(?!\\.))|(\\.\\d+)|(\\d+))(?:[eE][+-]?\\d+)?")); 

// Adds .. to list of symbols, symbol token matcher must appear before the operator token matcher
cp.addSymbols("(",")","[","]",",",".."); 
cp.setImplicitMultiplicationSymbols("(","["); 
cp.addOperatorTokenMatcher();

cp.addIdentifiers();
cp.addSemiColonTerminator();
cp.addWhiteSpaceCommentFilter();
cp.addBracketMatcher("(",")");
cp.addFunctionMatcher("(",")",",");

// Don't use the standard list matcher, use the ListOrRangeGrammarMatcher instead
//cp.addListMatcher("[","]",","); 
cp.addGrammarMatcher(
    new ListOrRangeGrammarMatcher(
        cp.getSymbolToken("["),
        cp.getSymbolToken("]"),
        cp.getSymbolToken(","),
        cp.getSymbolToken(".."),
        rangeOp));
cp.addArrayAccessMatcher("[","]");

Finally the Jep instance can be created and the higher order functions added.

Jep jep = new Jep(optab,cp, new StandardListProcessor());
jep.getFunctionTable().addFunction("map",new Map());
jep.getFunctionTable().addFunction("fold",new Fold());
jep.getFunctionTable().addFunction("filter",new Filter());
jep.getFunctionTable().addFunction("sort",new Sort());
jep.getFunctionTable().addFunction("apply",new Apply());
jep.getFunctionTable().addFunction("merge",new Merge());
jep.getFunctionTable().addFunction("iterate",new Iterate());
jep.getFunctionTable().addFunction("define",new Define());
jep.reinitializeComponents();
Since:
Jep 4.0 / Extensions 2.1
See Also:
Lambda function documentation