> What is the functional difference between a named construct "Params" and just allowing named parameters?
That "just" is doing a lot of work. I've not used PHP for a few years, but off the top of my head I can forsee the following problems:
- `call_user_func` would need to change to support this, e.g. accepting and passing-along named parameters.
- `call_user_func_array` would need to change, e.g. passing along associative-array arguments as named parameters.
- `func_get_args` would need to change, e.g. returning an associative array
Other parts of the standard library, like ReflectionParameter, would also need corresponding changes.
On their own I don't think those are necessarily bad. However, this would break a lot of code which relies on those functions and their invariants. For example, currying and partial application would become more complicated (e.g. http://chriswarbo.net/blog/2014-02-21-partial_application___... ).
I'm not necessarily against this change, but I would make the following points:
Extending APIs is a breaking change, since it breaks invariants/contracts that previously held (in this case by function definitions and call sites). This breaks backwards-compatibility, and that should be acknowledged and stated explicitly, rather than ignored. Here's a quick example of code which breaks, since it relies on the now-violated invariant that the parameter order of a function call matches that of the definition:
function call_with_strings() {
$args = func_get_args();
$f = array_shift($args);
$strings = [];
foreach ($args as $arg) {
$strings[] = strval($arg);
}
return call_user_func($f, $strings);
}
Secondly: there's a definite bandwagon effect between scripting languages like PHP/Python/JS/etc., for better (easier to transfer between) or worse (uncompelling monocultures lacking innovation/USP). Just because a feature exists in one, doesn't necessarily make it a good idea for the others (or the first, for that matter!); conversely, there are lots of great features out there which scripting languages don't seem to have picked up, and which are hardly ever brought up in these discussions. For example:
- Default arguments are generally supported, e.g. `parseInt(i, base=10)`. Alternative approaches to the same problem, like currying, are mostly absent, e.g. `parseIntFor(base, i); parseInt = parseIntFor(10);`
- Generators are generally supported, e.g. `for x in foo: yield x`. Alternative approaches to the same problem, like delimited continuations, are mostly absent, e.g. `reset; for x in foo: shift(x);`. This is especially interesting, since it's just an extension of exception handling, which is another generally-supported feature!
- Named parameters are generally supported, e.g. `foo(a=1, c=5)`. Alternative approaches to the same problem, like row-polymorphism, are mostly absent, e.g. `foo(['a' => 1, 'c' => 5])`.