Yesterday, I wrote about how $f() variable-function syntax works in PHP. While it is pretty bad, it’s also the groundwork for understanding the ways in which create_function is terrible.
No, I mean besides taking a string full of code as one of its arguments.
Consider this contrived example:
1 2 3 4 5 6 7 8 9 10 11 | <?php $input = array(1, 2, 3); $monolithic_dimensions = array_map( create_function('$elem', 'return $elem * $elem;'), $input ); /* Prints Array([0] => 1, [1] => 4, [2] => 9) */ print_r($monolithic_dimensions); ?> |
On the face of it, this looks like a decent approximation of functional programming idiom. However, every time PHP executes create_function, it adds a new function to the global function table.
What’s really happening is a little easier to see if you look at create_function’s return value:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?php $square = create_function('$elem', 'return $elem * $elem;'); print gettype($square) . "\n"; /* Prints string */ /* Prints 0 [] 108 [l] 97 [a] 109 [m] 98 [b] 100 [d] 97 [a] 95 [_] 49 [1] */ for ($i = 0; $i < strlen($square); $i++) { print ord($square[$i]) . "\t[" . $square[$i] . "]\n"; } ?> |
Yup. PHP is creating a function at runtime, with an “impossible” name (the zero byte isn’t allowed in function statements) to avoid collisions with user-defined functions.
Doesn’t C++ sort of do the same thing with virtual functions? What would you have it do instead?
I’d be curious to know if it creates a new function every time it is called with the same arguments.
No; C++’s virtual function tables are entirely generated at compile time, and the names are real symbols (well, fixed offsets) rather than string literals. This is a little easier to see in Objective-C, where the symbol table is in easy reach, but you can model C++’s behaviour with this C:
All of this happens at compile time.
As for the second part of your question:
So yes, it does re-create the function every time it’s called, even if you give it the exact same code. This doesn’t really surprise me; caching function bodies is the sort of advanced feature that needs to be implemented differently in every program.
For some ideas on how to abuse this in Objective-C, consider the links under isa swizzling. (Objective-C calls the pointer to an object’s virtual method table
isa.)So does it just purge the function table now and then? It must be doing something so as not to blow up the server because somebody hit a page that creates a function too many times.
Well, see, it’s not a big deal, because the interpreter starts, renders one page, and exits (destroying everything).
Hope you didn’t want to write a long-running program that isn’t a web page in it.