I was fooling around with variable composition today and had a cool idea. Before that, if you don't know what variable composition is then here are some examples of the neat manipulations PHP lets you do with variables.
// variable variables
$foo = 'bar';
$bar = 'hello';
echo $$foo; // outputs: 'hello'
// variable composition
$foo = 'bar';
echo ${'foo'}; // outputs: 'bar'
Essentially it is just different syntax for variables. However, with the right techniques, we can make it into so much more. For example, here is a composed variable that will actually execute a database UPDATE query:
// fake db query
function db_query($sql) {
// do query here...
echo $sql;
}
function query_error_handler($error_num, $error_str, $error_file, $error_line) {
if($error_num == 8 && preg_match("~^Undefined variable: update~i", $error_str)) {
return db_query(str_ireplace('Undefined variable: ', '', $error_str));
}
return FALSE;
}
set_error_handler('query_error_handler');
// perform a db query
!${"UPDATE mytable SET foo='bar'"};
You should be able to determine just from looking at this that you shouldn't use this type of hack in production code. Otherwise, for the curious programmer, it's definitely an interesting line to pursue. Now, on to Lambdas. My last article on closures/lambdas fixed a few bugs in my system and cleaned up the code; however, there was still the annoying of having to used ->call() to call the function. Essentially, I want to be able to do: lambda(...)(arg1[, arg1[, arg3[, ....]]]). Unfortunately this cannot be done. However, it can be approximated with variable composition. Check this out:
$lambda_1;
function lambda($args = '', $content = '') {
global $lambda_1;
$lambda_1 = create_function($args, $content);
return 'lambda_1';
}
echo ${lambda('$a', 'return $a;')}('hello world');
// output: 'hello world'
Clearly this code was set up specifically for this example, however I definitely think that this can be built on.
- PHP
by Peter Goodman on Jun 18, 2007 @ 8:55pm
Wow. While you're right that the technique is too hackish to use in production code, it's still amazingly insightful. On the first look through, it looked more like JavaScript's Prototype than PHP. I'm looking forward to seeing what all you can do with this.
Wow? Hackish? Insightful? No, it isn't.
What's the difference between that and using "create_function" directly? Exactly none. In fact, you cannot assign several "lambda" results to variables and pass them around, as every one would refer in fact to a string with the name of the same global (gasp!) variable. Programmer baby Jesus is already crying.
If you want to fool yourself with the idea that PHP has functional constructs, just assign the result of "create_function" to $func and use it with $func(params). Good luck if you use that, though.
That "lambda" thing of yours is nothing more than syntax saccharine (not even sugar) with zero practical value and many, many problems (ugliness is the least of them).
Sorry if I sound harsh, but this is what I think.
by Kankamuso on Aug 18, 2007 @ 12:07pm
In most ways you are right, this is not practical, it does not solve a problem, and it's generally quite an ugly solution. However, the goal of this was to look at php's limitations as a challenge and try to come up with a proof-of-concept way to call lambda-like functions at their creation instead of after their assignment. In this respect, I succeeded. I disagree with you that this code isn't insightful. As I've mentioned, this does not solve any realistic problems in PHP, and with respect to solving problems it is lacking insight. However, experimentation is healthy and I think that this was an insightful solution to the problem (or rather, a challenge to myself) of calling a created function on the spot.
by Peter Goodman on Aug 18, 2007 @ 12:14pm
As a side note, one of the things I dislike most with PHP is that functions are not objects and thus cannot be self-calling. The above hack using create_function semi solved the self-calling issue.
by Peter Goodman on Aug 18, 2007 @ 12:19pm
Technically a self calling function would be a callback function for an event, which of course does not exist in PHP. Nor is it supposed to, it's simply not the way PHP functions, if you need event based programming then go with a C# backend instead of using PHP.
by Seph on Aug 19, 2007 @ 6:37pm
My eyes! The goggles do nothing!
by Ranier Wolfcastle on Aug 20, 2007 @ 8:54am
I find the variable composition extremely useful, for instance if you're creating a Factory - often in a Factory pattern you will need to dynamically call constructors or methods. Normally I would do it like this:
$someMethodPrefix = 'populate';
$myDynamicParameter = 'MyClass';
$method = $someMethodPrefix . $myDynamicParameter;
$this->$method(); // $this->populateMyClasss();
Now, I can do it in a one-liner like this:
$this->{$someMethodPrefix.$myDynamicParameter}();
Thanks :)
by Carl on Aug 20, 2007 @ 9:42am
Hey, sorry for being late to the party but check this out:
//L is for lambda
$L = Array();
function lambda($args = '', $content = '') {
global $L;
$name = create_function($args, $content);
$L[$name] = $name;
return $name;
}
//and now you can do:
echo $L[lambda('$x','return $x;')]('hello world');
//and again
echo $L[lambda('$y','return $x*x;')](3.14);
Add a Comment