For example, PHP has two namespaces for functions: anonymous functions live in the regular variable namespace, so they can be passed around directly. Named (AKA global) functions are completely separate, so we can't pass them around as values. For example:
$my_anon = function() {};
function my_named() {}
// Valid
array_map($my_anon, []);
// Invalid
array_map(my_named, []);
As a workaround, whenever PHP sees a string when it's expecting a function, it will try to find a global function with a name matching the contents of the string. In other words, we can do: // Valid
array_map('my_named', []);
This is basically a weak form of eval: taking a string of PHP code ('my_named') and getting back the value it evaluates to (the my_named function). If you error-out for eval, you have to error-out for this, since the content of strings is runtime information and there's no way you can infer it well enough. For example: function smart_replace() {
$args = func_get_args();
$func = array_shift($args)? 'str' : 'preg';
return call_user_func_array("{$func}_replace", $args);
}
Other eval-like things in PHP include variable property lookups, variable method calls and "variable variables": $foo = "hello";
$object1->$foo = $object2->$foo; // Sets $object1's "hello" property to $object2's
$object3->$foo(); // Calls $object3's "hello" method
$bar = "foo";
echo $$bar; // Outputs hello
One interesting fact about these features is that, since they're not as powerful as a real eval, it can often be perfectly safe to supply them with unvalidated user input: array_map('str_' . $_GET['string_function'], $my_array);
There's no way we can swap out things like this reliably, and remember that these are not just "crazy uses of eval", they're officially sanctioned ways of working, which in some cases (eg. function names in strings) have no alternatives (short of redefining your own standard library).in your final example, you can replace the map with a big case switch of all known functions and an error clause.
That's of course, a lot of work. I'd guess it's just not worth it.
The parent was saying we could swap out all usages of 'old fashioned' functions like str_replace for some 'new fashioned' alternative, like String::replace, using some kind of upgrader tool.
I was pointing out that the PHP's eval-like features make it difficult for any such tool to exist. In particular, with Python or Javascript we might spit out a warning "Eval spotted; this upgrade might not work!". If we did the same in PHP, everyone would get a warning! "String used as function detected; this upgrade might not work!", "Variable variable detected; this upgrade might not work!", and so on.