Passing function names around as strings is, of course, a hideous consequence of using separate namespaces for functions (foo) and variables ($foo), so it's at least understandable.
Having to explicitly list a function's free variables with "use" is a hideous consequence of not having lexical scope from the start, so again it's understandable.
What I don't understand is why functions aren't first-class in PHP's parser. For example, the parser doesn't know that functions may be returned from other functions:
$foo = function() { return function() { echo "Hello;" }; };
$foo()(); // Parse error
Instead we have to perform some indirection like this: call_user_func($foo());
Or like this: $bar = $foo();
$bar();
Likewise, the parser doesn't realise that functions may be stored in objects: $baz = new stdClass;
$baz->quux = $foo();
$baz->quux(); // Error, no such method
Again, we have to add an indirection: call_user_func($baz->quux);
Or $foobar = $bar->quux;
$foobar();
Named functions can't be closures, even though we can declare them anywhere, presumably for historical reasons, ie. this is a syntax error: function foo($bar) {
function baz() use ($bar) {
echo $bar;
}
}
Another example of making it unnecessarily hard to use functions is iterable objects, which can only be iterated via foreach loops (ie. there is no way to map, reduce or filter them).Of course, I could also complain about no tail-call optimisation, functions not being curried, etc. but those aren't PHP-specific since very few scripting languages seem to get them right for some reason :(