[RFC] Parameter skipping, take 3

php.internals

Stas Malyshev

11 years ago
Hi! As I've got some questions on the topic, I'd like to revive and soon put to vote the parameter skipping RFC: https://wiki.php.net/rfc/skipparams For those who doesn't remember, quick reminder - it is about an ability to skip parameters in function calls so they'd take default value, like this: function foo($a, $b = true, $c = "abc") { ... } foo($x, default, $y); // $b gets to be true here In the last discussion I had a lot of "objections" to the tune of "we'd rather have named parameters". I like the idea of named parameters too, but this one does not contradict it - rather, it compliments it, and a lot of the extensions cleanup done in this patch also serves as a base for possible implementation of named params, if it happens (more on that in the RFC itself). The pull is at: https://github.com/php/php-src/pull/981 The patch has been reworked to work with PHP 7 engine changes, it is not perfect yet but in workable condition, and at this point I'd like to have a decision if we want to continue with it before I invest more time into covering the remaining corners. Note that the RFC has been changed in some details (e.g. variadics handling, but there's more) since the last time it was discussed, due to the changes in phpng, so I recommend re-reading the RFC even if you were familiar with it before.
-- Stas Malyshev smalyshev@gmail.com

Andrew Faulds

11 years ago
Hi Stas,
> On 5 Jan 2015, at 22:02, Stanislav Malyshev <smalyshev@gmail.com> wrote: > > For those who doesn't remember, quick reminder - it is about an ability > to skip parameters in function calls so they'd take default value, like > this: > function foo($a, $b = true, $c = "abc") { ... } > foo($x, default, $y); // $b gets to be true here > > In the last discussion I had a lot of "objections" to the tune of "we'd > rather have named parameters". I like the idea of named parameters too, > but this one does not contradict it - rather, it compliments it, and a > lot of the extensions cleanup done in this patch also serves as a base > for possible implementation of named params, if it happens (more on that > in the RFC itself).
Yes, they complement one another. Both exist because of horrible APIs. But I don’t think we should encourage horrible APIs. I don’t want to end up with the Windows API, except in PHP style: CreateWindowEx($foo, default, default, $bar, 0, 0, 100, 100, default, default, default, default); For well-designed functions, there is no need to skip parameters, either with a default keyword or with named parameters. So it’s a firm -1 from me. The solution to horrid APIs isn’t to add kludges to the language that make them slightly less painful. The solution is to fix them, or add new APIs, that are well designed. Thanks!
-- Andrea Faulds http://ajf.me/

Stas Malyshev

11 years ago
Hi!
> Yes, they complement one another. Both exist because of horrible > APIs. But I don’t think we should encourage horrible APIs.
You can create horrible APIs with this, but you can also create them without this. This doesn't make it any more likely, it just makes working with optional parameters easier.
> For well-designed functions, there is no need to skip parameters, > either with a default keyword or with named parameters.
I disagree with that and in general I disagree with the stance "I don't need this so the language does not need that". We can and should have a wider look than personal needs and preferences. There are many cases where optional parameters have their place, and making them more convenient is a good thing. As a witness to that, most of the languages with this syntax model (I'm not talking about the likes of Lisp of course) do allow optional parameters, and making it easy to work with them is a very frequently requested (and implemented) feature. You can, of course, say these all people are wrong and their code is horrible, but this is the reality of what people want and what they use. They'll do it whether you like it or not, but with this RFC it would be less painful. For me, it is a clear win.
-- Stas Malyshev smalyshev@gmail.com

Andrew Faulds

11 years ago
Hi Stas,
> On 5 Jan 2015, at 22:24, Stanislav Malyshev <smalyshev@gmail.com> wrote: > > Hi! > >> Yes, they complement one another. Both exist because of horrible >> APIs. But I don’t think we should encourage horrible APIs. > > You can create horrible APIs with this, but you can also create them > without this. This doesn't make it any more likely, it just makes > working with optional parameters easier.
Sure, but things like this make such APIs easier to work with. That’s not a good thing.
>> For well-designed functions, there is no need to skip parameters, >> either with a default keyword or with named parameters. > > I disagree with that and in general I disagree with the stance "I don't > need this so the language does not need that”.
It’s not that I don’t need this… there are some horrible APIs I’ve used which would be slightly (but only slightly) more pleasant to use with this feature. But I don’t think we should add features to the language to work around poor API design. We should get better APIs instead.
> We can and should have a > wider look than personal needs and preferences. There are many cases > where optional parameters have their place, and making them more > convenient is a good thing.
There are places where optional parameters are good. I never said they were bad. This RFC doesn’t help with optional parameters, it helps with excessive numbers of them, or optional parameters with weird default values. I don’t think that it is necessary to have parameter skipping for a well-designed API. If the default values are obvious and intuitive, as they should be, you don’t need “default”. If there is not an excessive number of parameters, you don’t need “default”. If your function takes so many arguments that you need “default”, you should probably reconsider your function’s signature. If someone else’s function does so, you should probably either fix it for them or write a wrapper function, so people trying to read and maintain your code don’t gradually go insane.
> As a witness to that, most of the languages > with this syntax model (I'm not talking about the likes of Lisp of > course) do allow optional parameters, and making it easy to work with > them is a very frequently requested (and implemented) feature.
Well, some of the languages. Others have decided that named parameters aren’t a good idea.
> You can, > of course, say these all people are wrong and their code is horrible, > but this is the reality of what people want and what they use. They'll > do it whether you like it or not, but with this RFC it would be less > painful. For me, it is a clear win.
I’m not sure if this RFC actually would make such functions that much less painful. For functions with a lot of default parameters, telling them apart is key. Seeing “NULL, FALSE, FALSE, 0, NULL” may orient the user better when scanning a parameter list than “default, default, default, default, default” would. Thanks!
-- Andrea Faulds http://ajf.me/

Stas Malyshev

11 years ago
Hi!
> Sure, but things like this make such APIs easier to work with. That’s > not a good thing.
For me, it is. Your stance is "if it's not ideal (in my opinion) design, we should not do anything to make it better". I think it's wrong - there are many opinions about what ideal design is, and yours has no inherent advantage over others. Removing the existing pain is always good for me, and telling people "rewrite all your code or live with the pain forever" is not a good practical stance. It may feel very purist and satisfying - "here we showed these horrible people how to do things right!" - but practically it is next to useless. PHP has always been a practical and not theory-purist language, and this IMO falls directly in this category.
> There are places where optional parameters are good. I never said > they were bad. This RFC doesn’t help with optional parameters, it > helps with excessive numbers of them, or optional parameters with
"Excessive" is a matter of opinion. If you have more than one of them, this RFC is helpful.
> Well, some of the languages. Others have decided that named > parameters aren’t a good idea.
I don't think the majority of PHP users here on your side: http://programmers.stackexchange.com/questions/27564/what-features-would-you-like-to-have-in-php Neither probably would be a majority of Python users. Or Ruby users. Of course, you can say all these people are horrible programmers who know nothing about designing APIs, but I'm afraid if you exclude all these from consideration when you design language features I'll get pretty lonely.
> them apart is key. Seeing “NULL, FALSE, FALSE, 0, NULL” may orient > the user better when scanning a parameter list than “default, > default, default, default, default” would.
Nobody would use "default, default, default, default" because that's meaningless, you could just not put them in. $foo, default, $bar would be much more frequent case, and that's what it is for. You can, of course, get it to absurd lengths, but so can be done to any feature.
-- Stas Malyshev smalyshev@gmail.com

Marcio Almada

11 years ago
Hi, Stanislav, great RFC. A huge part of core PHP API would benefit of parameter skipping. Andrea Faulds,
> It’s not that I don’t need this… there are some horrible APIs I’ve used
which would be slightly (but only slightly) more pleasant to use with this feature. But I don’t think we should add features to the language to work around poor API design. We should get better APIs instead. Not sure how this RFC rant is helpful since it's based on completely unreal alternatives. This "We should get better APIs instead" suggestion, in practice, means a ton of BC breaks that will never happen on PHP global functions for obvious reasons. 2015-01-05 19:51 GMT-03:00 Stanislav Malyshev <smalyshev@gmail.com>:

Andrew Faulds

11 years ago
Hi Marcio,
> On 5 Jan 2015, at 23:14, Marcio Almada <marcio.web2@gmail.com> wrote: > > Not sure how this RFC rant is helpful since it's based on completely unreal > alternatives. This "We should get better APIs instead" suggestion, in > practice, means a ton of BC breaks that will never happen on PHP global > functions for obvious reasons.
I’m not saying change existing APIs. I’m saying add new, parallel ones. We’ve done this before, we can do it again. It doesn’t break BC.
-- Andrea Faulds http://ajf.me/

Marcio Almada

11 years ago
> I’m not saying change existing APIs. I’m saying add new, parallel ones.
We’ve done this before, we can do it again. It doesn’t break BC. Makes sense to have new better overlapping APIs while old ones are slowly deprecated (which is still a (delayed) BC break). Thanks for clarifying this, anyway. But I still disagree when you say that parameter skipping would instantly "encourage horrible APIs". That's a huge stretch, IMMO, unless you have any real case to support such statement. 2015-01-05 20:17 GMT-03:00 Andrea Faulds <ajf@ajf.me>:

Rowan Collins

11 years ago
On 05/01/2015 22:35, Andrea Faulds wrote:
> If the default values are obvious and intuitive, as they should be, you don’t need “default”.
It's not always a case of not knowing what the default values are; sometimes it's a case of not knowing - and not wanting to worry about - what they might be in the future. For instance, you might have an integer parameter representing some kind of cost-benefit tradeoff, with a "best practice" value as default, which happened to be the second of 3 well-defined parameters. To specify the third parameter, you need some way of saying "I'll accept the best practice for the second parameter, thanks". There are a few options we can consider: - You just hard-code the current documented value, leaving a comment that you have no idea what it means, or whether it might change. Clearly not optimal. - The library allows some special-case value, such as NULL, to be passed. Not particularly readable, because it's not clear what NULL means in this context, or whether you've just messed up and it will be coerced to int(0). On the other hand, allows calling with a variable set to NULL (or other magic value) to select the default behaviour at run-time. - The library defines a constant containing the default value, such as DEFAULT_FOO_COST. More readable, but relies on the library author having a good naming convention so that you don't have to keep going to the manual to find it. - The proposed "default" keyword. More explicit than NULL, supported out-the-box without any effort on the part of the library author, lets you get on with your job. On the other hand, doesn't address the case where you want to select the default at run-time, e.g. foo('bar', $_GET['cost'] ?? default, 'baz') doesn't work; this is however true of existing optional parameters, it's just that they can only come at the end of the list.
> I’m not sure if this RFC actually would make such functions that much less painful. For functions with a lot of default parameters, telling them apart is key. Seeing “NULL, FALSE, FALSE, 0, NULL” may orient the user better when scanning a parameter list than “default, default, default, default, default” would.
A list of all defaults is clearly a straw man, since it would be a daft use of this feature. However, "10, null, default, 0" is clearer in its intent than "10, null, false, 0" - the 1st, 2nd and 4th parameters have been specifically chosen by the programmer, while the 3rd is left to the implementation to choose. Named parameters do seem to offer a solution to a lot of the same use cases, but they have their drawbacks too - for instance, currently, parameter names are implementation details private to the function, and a straight implementation of named parameters would make them public overnight. However, as Stas says, the two mechanisms can coexist and complement each other, and if we get both it can be left to a matter of personal taste or style guides.
-- Rowan Collins [IMSoP]