I’m investigating user-defined lambda-like functions as discussed here.
Is this something of interest to discuss here?
User-defined functions
JMESPath already supports expression-type which are, conceptually, anonymous functions without arguments.
I have toyed with the idea of extending exprefs to support named arguments.
An updated grammar that works looks like this:
expression-type = "&" expression / "<" arguments ">" "=>" expression
arguments = variable-ref *( "," variable-ref
It requires a new token => which is even not absolutely necessary. Parsing involves a new entry in the nud() function to match on token < (less-than-sign).
Reduce function
As expression-type are only supported as function arguments, a reduce()
function could work like this:
reduce(array $array, any $seed, expr [any, any]->any)
Example:
reduce(@, `1`, <$acc, $cur> => $acc × $cur)
The reduce() function knows how to iterate over its first array argument
and repeatedly create bindings for both function arguments $acc and $cur.
Funnily enough, the lambda function does not support natively the @ current node.
An argument can be made that it could be similar to the $cur argument. In that case,
a choice must be made as to which "context" is specified when evaluating the expref.
Reusing user-defined functions
I then investigated what reusing user-defined functions could look like.
This requires a mechanism to store or hold functions, possibly by name,
as well as a way to call those functions with appropriate parameters.
By taking advantage of the hopefully upcoming let-expression design, one
could bind the anonymous function to a variable reference. Then, syntax for
calling the function using this variable must be extended and supported in
the grammar.
In the following expression:
let $concat = <$lhs, $rhs> => join('-', [$lhs, $rhs])
in $concat('4', '2')
$concat is bound to the <$lhs, $rhs> => join('-', [$lhs, $rhs]) lambda expression-type. Then, $concat('4', '2') invokes the function indirectly using the $concat variable reference.
The following grammar changes is required:
function-expression = ( unquoted-string / variable-ref ) no-args / one-or-more-args )
Again, implementation is quite easy.
Funnily enough, having also implemented arithmetic-expression grammar rules, I was then able to implement the recursive Fibonacci sequence using the following expression:
let $fib = <$n> => (
($n == `0` && `0`) ||
(($n == `1` && `1`) ||
( $fib($n - `1`) + $fib($n - `2`) )
)
) in
$fib(@)
I’m investigating user-defined lambda-like functions as discussed here.
Is this something of interest to discuss here?
User-defined functions
JMESPath already supports
expression-typewhich are, conceptually, anonymous functions without arguments.I have toyed with the idea of extending exprefs to support named arguments.
An updated grammar that works looks like this:
It requires a new token
=>which is even not absolutely necessary. Parsing involves a new entry in thenud()function to match on token<(less-than-sign).Reduce function
As
expression-typeare only supported as function arguments, areduce()function could work like this:
reduce(array $array, any $seed, expr [any, any]->any)Example:
The
reduce()function knows how to iterate over its first array argumentand repeatedly create bindings for both function arguments
$accand$cur.Funnily enough, the lambda function does not support natively the
@current node.An argument can be made that it could be similar to the
$curargument. In that case,a choice must be made as to which "context" is specified when evaluating the expref.
Reusing user-defined functions
I then investigated what reusing user-defined functions could look like.
This requires a mechanism to store or hold functions, possibly by name,
as well as a way to call those functions with appropriate parameters.
By taking advantage of the hopefully upcoming
let-expressiondesign, onecould bind the anonymous function to a variable reference. Then, syntax for
calling the function using this variable must be extended and supported in
the grammar.
In the following expression:
$concatis bound to the<$lhs, $rhs> => join('-', [$lhs, $rhs])lambdaexpression-type. Then,$concat('4', '2')invokes the function indirectly using the$concatvariable reference.The following grammar changes is required:
Again, implementation is quite easy.
Funnily enough, having also implemented
arithmetic-expressiongrammar rules, I was then able to implement the recursive Fibonacci sequence using the following expression: