Wednesday, June 30, 2010

voltron and "fluent lambdas"

For lack of a better name I am sticking with "fluent lambda" which essentially is how I get around the lack of nice lambdas in php. Even in php 5.3 I find the function($val) { return $val + 1; } syntax to be overkill. I would much rather see L(val)->add(1)

Lets say you have a list of names and you want to reverse them, uppercase them and then join them by an & symbol. Currently in raw php you have a few options but the cleanest is probably something to the effect of either:

Idiomatic php:

$names = array('peter', 'paul', 'mary');
foreach($names as $key => $val) {
$names[$key] = strtoupper(strrev($val));
}
echo join('&', $names);


Functional php:

$names = array('peter', 'paul', 'mary');
echo join('&', array_map(create_function('$val', 'return strtoupper(strrev($val));'), $names));


Functional php 5.3:

$names = array('peter', 'paul', 'mary');
echo join('&', array_map(function($val) { return strtoupper(strrev($val)); }, $names))


Voltron:

$names = newArray(VString, 'peter', 'paul', 'mary');
echo $names->map(L(val)->reverse->upper)->join('&');


This works by the global function L which takes either 'key' or 'val as an argument and then returns a created function which passes along the same method chain.

Where the real advantage comes to not passing around "string lambdas" i.e. the create_function approach - is when you start dealing with nested lambdas i.e.

functional php:

$listOfList = array(
array('a', 'b', 'c'),
array('d', 'e', 'f'));

echo join('<hr>', array_map(create_function('$val', 'return join(\',\', array_map(create_function(\'$val\', \'return strtoupper($val);\'), $val));'), $listOfList));


Voltron:

$listOfList = newArray(VArray,
newArray(VString, 'a', 'b', 'c'),
newArray(VString, 'd', 'e', 'f'));

echo $listOfList->map(L(val)->map(L(val)->upper)->join(','))->join('<hr>');


So whats next? I am probably going to integrate this with my closure class from my lisp so that you can pass in vars, but immediately my needs are mainly for calling methods on objects in a given array. But I can imagine that being one of the first annoyances people run into.

Basically I am trying to get at the idea that oneliners don't have to be made of gnarleston heston.

perl:

@p=(0,1);until($#p>20){print"$p[-2]\n";push @p,$p[-2]+$p[-1]}


Voltron:

echo newRange(0, 1)->expand(L(x)->add(y), 20)->join("\n");


Here is an example of finding primes.

Python:

noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
primes = [x for x in range(2, 50) if x not in noprimes]


Voltron:

$noprimes = newRange(2, 8)->map(N(VRange, L(y)->times(2), 50, y))->flatten;
$primes = newRange(2, 50)->diff($noprimes);