PHP 8 has named parameters in function calls, Kotlin has named parameters in
function calls.
Kotlin has this handy feature that you can put parameters with defaults
before normal ones. Those parameters can then only be used by naming them.
See also: https://kotlinlang.org/docs/functions.html#default-arguments
This is very useful because I can add an optional parameter to a function
and prevent users of my function from using the parameter in a positional
way. This way I don't have to make a compatibility promise to never change
the position of this parameter.
If I try the same thing in PHP 8.0 I get a Deprecated warning and if I try
it in PHP 8.1 I get something that I don't understand:
https://3v4l.org/cg4DA
This is very useful because I can add an optional parameter to a function
and prevent users of my function from using the parameter in a positional
way. This way I don't have to make a compatibility promise to never change
the position of this parameter.
I would much prefer we could find a way to give this proper support
rather than a hack.
I frequently use large numbers of named arguments and would very much
like to be able to knock out the ability to use positional arguments,
thus ensuring I can change the order (e.g. inserting a new argument
after a related one) without a BC break.
If I try the same thing in PHP 8.0 I get a Deprecated warning and if I try
it in PHP 8.1 I get something that I don't understand:
https://3v4l.org/cg4DA
There are two diagnostics showing in 8.1, the deprecation on the
declaration, and a fatal error on the call.
What's happened is that given your signature:
function blah($foo = "deffoo", $bar) { ... }
PHP has decided it doesn't make sense, and re-interpreted it as this:
function blah($foo, $bar) { ... }
Then when you try to call it:
blah(bar: "1");
You're missing the now-mandatory parameter $foo, so you get a fatal error.
I'm not sure exactly why this behaviour has changed, and can't see any
mention in the Release or Migration pages in the manual. It's not a
huge break, because named params have only existed since 8.0, but it
is technically a breaking change in a minor version.
The only relevant discussion I've found is this, where Nikita is I think
hinting at the new behaviour: https://externals.io/message/114007#114026
Regards,
--
Rowan Tommins
[IMSoP]
If I try the same thing in PHP 8.0 I get a Deprecated warning and if I
try
it in PHP 8.1 I get something that I don't understand:
https://3v4l.org/cg4DAThere are two diagnostics showing in 8.1, the deprecation on the
declaration, and a fatal error on the call.What's happened is that given your signature:
function blah($foo = "deffoo", $bar) { ... }
PHP has decided it doesn't make sense, and re-interpreted it as this:
function blah($foo, $bar) { ... }
Then when you try to call it:
blah(bar: "1");
You're missing the now-mandatory parameter $foo, so you get a fatal error.
I'm not sure exactly why this behaviour has changed, and can't see any
mention in the Release or Migration pages in the manual. It's not a
huge break, because named params have only existed since 8.0, but it
is technically a breaking change in a minor version.The only relevant discussion I've found is this, where Nikita is I think
hinting at the new behaviour: https://externals.io/message/114007#114026
The new behavior has been introduced[1] quite a while after this mail
had been sent. I agree with the idea outlined in the commit message.
I suggest to document that in the migration guide, and in the manual proper.
[1]
https://github.com/php/php-src/commit/afc4d67c8b4e02a985a4cd27b8e79b343eb3c0ad
--
Christoph M. Becker
The new behavior has been introduced[1] quite a while after this mail
had been sent. I agree with the idea outlined in the commit message.I suggest to document that in the migration guide, and in the manual proper.
Good spot. I guess it does make sense to treat this as an accident in
8.0, rather than a feature that was added and then immediately removed.
I've raised a PR to add this to the Migration Guide, and update the
general description of optional parameters:
https://github.com/php/doc-en/pull/1191
For some reason, the CI build failed on that PR, but on unrelated files,
so I'm not sure if it's my fault or not.
Regards,
--
Rowan Tommins
[IMSoP]
For some reason, the CI build failed on that PR, but on unrelated
files, so I'm not sure if it's my fault or not.
Ah no, it was me. Build passing now.
--
Rowan Tommins
[IMSoP]
Четверг, 9 декабря 2021, 8:22 +03:00 от André Hänsel andre@webkr.de:
PHP 8 has named parameters in function calls, Kotlin has named parameters in
function calls.Kotlin has this handy feature that you can put parameters with defaults
before normal ones. Those parameters can then only be used by naming them.
See also: https://kotlinlang.org/docs/functions.html#default-argumentsThis is very useful because I can add an optional parameter to a function
and prevent users of my function from using the parameter in a positional
way. This way I don't have to make a compatibility promise to never change
the position of this parameter.If I try the same thing in PHP 8.0 I get a Deprecated warning and if I try
it in PHP 8.1 I get something that I don't understand:
https://3v4l.org/cg4DA--
To unsubscribe, visit: https://www.php.net/unsub.php
I'll add that leading optional parameters are needed to implement currying and partial application.
function foo(int $opt = 42, int $req) {}
$foo = curry(foo(...), 23);
// $foo = fn($opt = 42, $req = 23);
While this is not a popular practice in PHP, this deprecation notification «breaks» all code that uses functional pradigm/concepts.
Kirill Nesmeyanov
I'll add that leading optional parameters are needed to implement currying and partial application.
function foo(int $opt = 42, int $req) {} $foo = curry(foo(...), 23); // $foo = fn($opt = 42, $req = 23);
I'm confused what the optional parameter is doing here - is it just to
avoid telling the curry function which argument you're fixing? And
wouldn't both currying and partial application result in a
single-argument closure there, not just making both parameters optional?
I would expect it to look something like this:
function foo(int $a, int $b) {}
$foo = partial(foo(...), 23, 0);
// $foo = fn($b) => foo(23, $b);
$foo = partial(foo(...), 23, 1);
// $foo = fn($a) => foo($a, 23);
$bar = curry(foo(...));
// $bar = fn($a) => fn($b) => foo($a, $b);
While this is not a popular practice in PHP, this deprecation notification «breaks» all code that uses functional pradigm/concepts.
That's clearly an exaggeration; it's clearly possible to write
functional-style code without making use of this particular trick. If it
is a common trick, then that's worth considering, but it would be good
to see some evidence of that.
Regards,
--
Rowan Tommins
[IMSoP]
Вторник, 14 декабря 2021, 12:21 +03:00 от Rowan Tommins rowan.collins@gmail.com:
I'll add that leading optional parameters are needed to implement currying and partial application.
function foo(int $opt = 42, int $req) {} $foo = curry(foo(...), 23); // $foo = fn($opt = 42, $req = 23);
I'm confused what the optional parameter is doing here - is it just to
avoid telling the curry function which argument you're fixing? And
wouldn't both currying and partial application result in a
single-argument closure there, not just making both parameters optional?I would expect it to look something like this:
function foo(int $a, int $b) {} $foo = partial(foo(...), 23, 0); // $foo = fn($b) => foo(23, $b); $foo = partial(foo(...), 23, 1); // $foo = fn($a) => foo($a, 23); $bar = curry(foo(...)); // $bar = fn($a) => fn($b) => foo($a, $b);
While this is not a popular practice in PHP, this deprecation notification «breaks» all code that uses functional pradigm/concepts.
That's clearly an exaggeration; it's clearly possible to write
functional-style code without making use of this particular trick. If it
is a common trick, then that's worth considering, but it would be good
to see some evidence of that.Regards,
--
Rowan Tommins
[IMSoP]--
To unsubscribe, visit: https://www.php.net/unsub.php
Yep, you rightly noticed, I gave an example completely incorrectly.
I got acquainted with this approach with the reverse order of arguments by default while studying lambda calculus, but now I can no longer remember in what cases they are used =\
Sry for that.
Kirill Nesmeyanov
I'll add that leading optional parameters are needed to implement
currying and partial application.function foo(int $opt = 42, int $req) {} $foo = curry(foo(...), 23); // $foo = fn($opt = 42, $req = 23);
While this is not a popular practice in PHP, this deprecation
notification «breaks» all code that uses functional pradigm/concepts.
Kirill Nesmeyanov
This is simply untrue, and I have not seen any code that does currying in that fashion. If anything, trailing optional arguments are what make currying difficult as it's unclear when to "stop" and invoke the underlying function. (The previous PFA RFC had that solved.)
I do not like the original proposal here either, though. If we decide we want to allow an argument to require that it be called named, that should have an explicit keyword to indicate such. It should not be an implicit trick of otherwise confusing argument ordering.
--Larry Garfield