a .NET hosted scripting language with a focus on meta-programming and embedded DSLs
I'm talking about Currying, "the technique of transforming a function that takes multiple arguments into a function that takes a single argument…"
With two recent additions to Prexonite (Script), it has become very easy to implement higher-order functions, including "curry" and "uncurry". With "additions" I'm referring to Closures as a virtual machine feature and Lambda Expressions as a Prexonite Script expansion.
Something of the form (a1, a2, a3, ... , an) => expr
is an expression that is compiled into a separate function.
Instead of a value, such a construct returns a closure, an enhanced reference to that anonymous function, that acts like a normal function reference.
It get's even better: As this so called lambda expression is defined inside another function, you can use local variables as if they were part of the expression. That's also the reason why this closure-thingy is returned instead of a normal function reference: It carries information about additional local variables available to the lambda expression.
But now, let's get back to
unction curry(ref f) = a => b => f(a,b);
function uncurry(ref f) = (a, b) =>
{
ref bc = f(a);
return bc(b);
};
function map(ref f, lst)
{
var nlst = new List;
foreach(var x in lst)
nlst.Add( f(x) );
return nlst;
}
I admit that these functions are limited to a total number of two arguments. It's more a proof-of-concept, as it's very rare that you actually need something like this in an imperative language like Prexonite Script.
One of my unit tests uses currying to partially apply an addition to a list of integers
map( curry( (x,y) => x + y ) , ~List.Create( 2, 3, 5 ))
In this case, curry returns a function that takes the one argument (x
) and itself returns a function that takes the other argument (y
) and returns x + y
.
So the result of this expression can be written as:
var additions = ~List.Create( y => 2+y, y => 3+y, y => 5+y );
To finally get a list of integers again, you'll have to supply the missing y, either using a for (each) loop or by treating the list itself as a reference and passing one argument:
var results = additions(5);
The result is again a list. And no, this is not a case study. It's reality. (I'm sorry, I'm just a bit like "Closures! In my own programming language! Working!")