quasi blocchi in php
08 December 2006 // php. stuff.
Every programmer knows that iterators are generally better than loops. Although php has a variety of iterator functions, their use is seriously limited, because there is no way to pass user code to the iterator.
The overly verbose create_function() is a very unequal replacement for lambdas or blocks, but in php we have no other choice. We can only try to reduce verbosity.
function qe($body) {
static $cache = array();
if(!isset($cache[$body])) {
$argc = 0;
preg_replace('/\$(\d)/e', '$argc = max($argc, $1)', $body);
$args = '$_' . implode("='',\$_", range(0, $argc)) . "=''";
$expr = preg_replace('/\$(\d)/', '$_$1', $body);
$cache[$body] = create_function($args, "return $expr;");
}
return $cache[$body];
}
qe() (= "quoted expression") creates a dynamic function from an expression given in a string. $0...$9 act as function parameters (like in preg_replace). Examples
# find odd numbers < 30
$a = array_filter(range(1, 30), qe('$0 % 2'));
print_r($a);
# muliply two arrays
$a = array(3, 5, 7);
$b = array(4, 6, 8);
$product = array_map(qe('$0 * $1'), $a, $b);
print_r($product);
Unlike create_function, qe also caches its results, so that the identical functions are created only once. This is quite practical when calling qe in a loop.
qe requires its argument to be an expression, i.e. no operators are allowed. The slight variation called qf ("quoted function") takes the complete function body as an argument.
function qf($body) {
static $cache = array();
if(!isset($cache[$body])) {
$argc = 0;
preg_replace('/\$(\d)/e', '$argc = max($argc, $1)', $body);
$args = '$_' . implode("='',\$_", range(0, $argc)) . "=''";
$expr = preg_replace('/\$(\d)/', '$_$1', $body);
$cache[$body] = create_function($args, "$expr;");
}
return $cache[$body];
}
Example
$apples = array(0, 1, 2, 3);
$messages = array_map(qf('
if($0 == 0) return "no apples";
if($0 == 1) return "one apple";
else return "$0 apples"
'), $apples);
print_r($messages);
Of course, this kind of code only makes sense with very short function definitions.
comment on this