The language is trivial. Everything is either a symbol, a function call, a list, a string or a number. The grammar is very simple:
<literal>::= "string" | 'string' | [0-9]\.[0-9] <symbol> ::= [^,()\[\]] <comma-expression> ::= <expression> | <expression> ',' <comma-expression> <symbol-or-literal> ::= <symbol> | <literal> <term> ::= '[' <comma-expression> ']' | <symbol-or-literal> <expression> ::= <term> | <term> '(' <comma-expression ')'
Strings, lists and numbers can be called without arguments and evaluate to themselves. Everything is prefix notation, eg: to add four numbers, you need +(1,2,3,4).
Calls expression with arguments. Eg:
Decomposes functioncall into a list with the function as head and the list of the arguments as tail. Eg:
decompose(+(1,2,3)) => [+,[1,2,3]]
This works like lambda(), but also binds the resulting anonymous function to a name.
In effect it is the same as
Given a list of vars, replaces each variable with its corresponding positional argument everywhere in expression. Beware that the bindings of the lambda's variables can be cached, so if a function's return value may vary across calls with identical arguments, you are likely to end up with unexpected results.
As an example you could create an anonymous function that takes two arguments (a and b) and returns their sum:
Then call it:
lambda([a,b],+(a,b))(1,2) => 3
Unbinds name, returning the previous expression that name was bound to, eg: