[RFC] Argument unpacking

php.internals

Nikita Popov

13 years ago
Hi internals! This RFC proposes to add a syntax for argument unpacking: https://wiki.php.net/rfc/argument_unpacking Basically, this is the "complement" of the variadics RFC: It is not about declaring variadic functions, but about calling them. The syntax it introduces looks as follows: $db->query($query, ...$params); Thoughts? Thanks, Nikita

Laruence

13 years ago
On Fri, Aug 30, 2013 at 11:23 PM, Nikita Popov <nikita.ppv@gmail.com> wrote:
> Hi internals! > > This RFC proposes to add a syntax for argument unpacking: > > https://wiki.php.net/rfc/argument_unpacking > > Basically, this is the "complement" of the variadics RFC: It is not about > declaring variadic functions, but about calling them. > > The syntax it introduces looks as follows: > > $db->query($query, ...$params);
seems so weird and ugly.. -1 thanks
> > Thoughts? > > Thanks, > Nikita
-- Laruence Xinchen Hui http://www.laruence.com/

Levi Morrison

13 years ago
On Fri, Aug 30, 2013 at 10:33 AM, Laruence <laruence@php.net> wrote:
> On Fri, Aug 30, 2013 at 11:23 PM, Nikita Popov <nikita.ppv@gmail.com> > wrote: > > Hi internals! > > > > This RFC proposes to add a syntax for argument unpacking: > > > > https://wiki.php.net/rfc/argument_unpacking > > > > Basically, this is the "complement" of the variadics RFC: It is not about > > declaring variadic functions, but about calling them. > > > > The syntax it introduces looks as follows: > > > > $db->query($query, ...$params); > seems so weird and ugly.. > > -1 > > thanks
Compared to the current alternatives it's definitely less ugly. I'm all for this syntax addition.

Yo-An Lin

11 years ago
Laruence <laruence <at> php.net> writes:
> > On Fri, Aug 30, 2013 at 11:23 PM, Nikita Popov <nikita.ppv <at> gmail.com> > wrote: > > Hi internals! > > > > This RFC proposes to add a syntax for argument unpacking: > > > > https://wiki.php.net/rfc/argument_unpacking > > > > Basically, this is the "complement" of the variadics RFC: It is not about > > declaring variadic functions, but about calling them. > > > > The syntax it introduces looks as follows: > > > > $db->query($query, ...$params); > seems so weird and ugly.. > > -1
I totally agree.. the syntax design doesn't look quiet right. it isn't readable and ugly. Since it's unpacking the arguments from the caller, the "..." should be put after the $params. e.g. $db->query($query, $params...); the above approach is also used in Go. Cheers, c9s https://github.com/c9s

Rowan Collins

11 years ago
Yo-An Lin wrote on 05/06/2015 06:51:
> Laruence <laruence <at> php.net> writes: > >> On Fri, Aug 30, 2013 at 11:23 PM, Nikita Popov <nikita.ppv <at> gmail.com> >> wrote: >>> Hi internals! >>> >>> This RFC proposes to add a syntax for argument unpacking: >>> >>> https://wiki.php.net/rfc/argument_unpacking >>> >>> Basically, this is the "complement" of the variadics RFC: It is not about >>> declaring variadic functions, but about calling them. >>> >>> The syntax it introduces looks as follows: >>> >>> $db->query($query, ...$params); >> seems so weird and ugly.. >> >> -1 > I totally agree.. the syntax design doesn't look quiet right. it isn't > readable and ugly. > > Since it's unpacking the arguments from the caller, the "..." should be put > after the $params. e.g. > > $db->query($query, $params...); > > the above approach is also used in Go.
Not sure why you've picked this up now, but the mail you're replying to is from nearly two years ago, and the syntax in question was accepted, and released as part of PHP 5.6.0 in August 2014. The documentation can be found here: http://php.net/functions.arguments#functions.variable-arg-list So it's far too late to change the syntax, even if we had a better reason than "it looks nicer to me with the ... the other side of the name". Regards,
-- Rowan Collins [IMSoP]

Stas Malyshev

13 years ago
Hi!
> This RFC proposes to add a syntax for argument unpacking: > > https://wiki.php.net/rfc/argument_unpacking > > Basically, this is the "complement" of the variadics RFC: It is not about > declaring variadic functions, but about calling them.
This is just another way of doing call_user_func, I'm not sure we really need it. And something like: test(1, 2, ...[3, 4], 5, 6, ...[7, 8]) looks plain weird. What would be the use case for doing something like that? I don't think we should add this.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Nikita Popov

13 years ago
On Fri, Aug 30, 2013 at 6:57 PM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:
> And something like: > test(1, 2, ...[3, 4], 5, 6, ...[7, 8]) > > looks plain weird. What would be the use case for doing something like > that?
No use case at all. This is a technical specification, so I write down what is possible, not necessarily what you'd write in your code. Of course it makes no sense to write something like ...[1, 2, 3], because you could just as well write 1, 2, 3 directly. The point of that example is that it's possible to mix it with normal arguments. The "practical" example for that is the example in the introduction: $db->query($query, ...$params). Here a "normal" argument is followed by an unpacked argument.
> This is just another way of doing call_user_func, I'm not sure we really
need it. Assuming you mean call_user_func_array, yes. This is just syntax sugar for call_user_func_array. Advantages of this syntax over cufa are outlined here: https://wiki.php.net/rfc/argument_unpacking#advantages_over_call_user_func_array Thanks, Nikita

Stas Malyshev

13 years ago
Hi!
> Assuming you mean call_user_func_array, yes. This is just syntax sugar > for call_user_func_array. Advantages of this syntax over cufa are > outlined here: > https://wiki.php.net/rfc/argument_unpacking#advantages_over_call_user_func_array
The only case that I see that could make sense is $db->query($query, ...$params). Multiple unpackings make no sense to me, as it is impossible to know which argument ends up where and no corresponding syntax exists on function side. Also, no other language as far as I can see allows it. Also, I just noticed the RFC tries to sneak in the exception throwing in the syntax construct, which we agreed not to do a long time ago and which was never done in the engine. We shouldn't do this - if you want to change PHP error handling, it should be in separate RFC for this purpose.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Nikita Popov

13 years ago
On Fri, Aug 30, 2013 at 7:45 PM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:
> Hi! > > > Assuming you mean call_user_func_array, yes. This is just syntax sugar > > for call_user_func_array. Advantages of this syntax over cufa are > > outlined here: > > > https://wiki.php.net/rfc/argument_unpacking#advantages_over_call_user_func_array > > The only case that I see that could make sense is $db->query($query, > ...$params). >
> Multiple unpackings make no sense to me, as it is impossible to know > which argument ends up where and no corresponding syntax exists on > function side. Also, no other language as far as I can see allows it. >
Not sure I get what you mean. All languages with argument unpacking allow this. It's not commonly needed, but there are uses for it and I don't see a reason why one should explicitly disallow doing multiple unpacks. If you want a practical example for this, consider partial application, where you bind a number of arguments to a function. An "old-style" definition for this (no variadics syntax, no argument unpack) would look like this: function bind(callable $function) { $boundArgs = array_slice(func_get_args(), 1); return function() use ($function, $boundArgs) { return call_user_func_array( $function, array_merge($boundArgs, func_get_args() ); } } The equivalent new-style definition with variadics syntax and argument unpacking: function bind(callable $function, ...$boundArgs) { return function(...$args) use($function, $boundArgs) { return $function(...$boundArgs, ...$args); } } As you can see, here two arguments are unpacked in one call.
> Also, I just noticed the RFC tries to sneak in the exception throwing > in the syntax construct, which we agreed not to do a long time ago and > which was never done in the engine. We shouldn't do this - if you want > to change PHP error handling, it should be in separate RFC for this > purpose. >
I tried to make sure that this does not "sneak in" but is mentioned prominently (it's half of the by-ref section). Anyway, as already mentioned in the RFC: Exceptions are how we deal with errors relating to Traversables in general. Yes, also in the engine. E.g. in the foreach implementation, if get_iterator fails an exception is thrown: http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_vm_def.h#4191 If staying consistent with foreach is not wanted (or this is not considered "consistent"), I'm also okay to turn that into a fatal error or into a warning where the argument will simply be passed without the reference-binding instead (like what we do when you pass a function call that returns by-value to a by-reference parameter. Though there it's actually just an E_STRICT.) Nikita

Stas Malyshev

13 years ago
Hi!
> Not sure I get what you mean. All languages with argument unpacking > allow this. It's not commonly needed, but there are uses for it and I
I mean this:
>>> a = [0,3] >>> range(*a)
[0, 1, 2]
>>> a = [1]; b = [2] >>> range(*a, *b)
File "<stdin>", line 1 range(*a, *b) ^ SyntaxError: invalid syntax
>>> a=[0] >>> range(*a, 3)
File "<stdin>", line 1 SyntaxError: only named arguments may follow *expression
> don't see a reason why one should explicitly disallow doing multiple > unpacks.
Because it makes very hard to understand what's going on and makes no sense semantically.
> As you can see, here two arguments are unpacked in one call.
This is very special use case to be hidden in library functions, I don't think we need to have language syntax specially directed at that, at the cost of making it overall more complex and hard to understand. I can see what "add all those params at the end" syntax mean. However having something like ($a, ...$b, $c, ...$d, $e, $f, $g, ...$h) I have no idea what's going on at all and what is sent where.
> I tried to make sure that this does not "sneak in" but is mentioned > prominently (it's half of the by-ref section). Anyway, as already > mentioned in the RFC: Exceptions are how we deal with errors relating to > Traversables in general. Yes, also in the engine. E.g. in the foreach > implementation, if get_iterator fails an exception is thrown: > http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_vm_def.h#4191
This is the only instance of exception in the engine, and it is very unfortunate. However what is proposed in this RFC is using exception for one special case of factual argument not matching function definition, while exceptions are never used in any other case of the same problem. This is inconsistent and wrong.
> If staying consistent with foreach is not wanted (or this is not
How calling a function can be consistent with foreach? Those are different things. Calling a function should be consistent with all other cases of calling a function.
> considered "consistent"), I'm also okay to turn that into a fatal error > or into a warning where the argument will simply be passed without the > reference-binding instead (like what we do when you pass a function call > that returns by-value to a by-reference parameter. Though there it's > actually just an E_STRICT.)
it should work like other instances of non-ref parameter (i.e. not a variable and not a function returning by ref) passed to by-ref function. Namely producing E_STRICT.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Lazare Inepologlou

13 years ago
2013/8/30 Stas Malyshev <smalyshev@sugarcrm.com>
> > don't see a reason why one should explicitly disallow doing multiple > > unpacks. > > Because it makes very hard to understand what's going on and makes no > sense semantically. > > > As you can see, here two arguments are unpacked in one call. > > This is very special use case to be hidden in library functions, I don't > think we need to have language syntax specially directed at that, at the > cost of making it overall more complex and hard to understand. I can see > what "add all those params at the end" syntax mean. However having > something like ($a, ...$b, $c, ...$d, $e, $f, $g, ...$h) I have no idea > what's going on at all and what is sent where. > >
I agree with Stas here. If an argument comes after an unpacked array, its position is not certain until runtime. This makes life difficult for static analysis tools, which is one of the reasons for introducing the new syntax. Even in the use case of Nikita, the two arguments to be unpacked come without any standard arguments between or after them. I suggest that argument unpacking should be limited to the last arguments only. Lazare Inepologlou Ingénieur Logiciel
--

Bob Weinand

13 years ago
Hi! Am 31.8.2013 um 00:27 schrieb Lazare Inepologlou <linepogl@gmail.com>:
> 2013/8/30 Stas Malyshev <smalyshev@sugarcrm.com> > >>> don't see a reason why one should explicitly disallow doing multiple >>> unpacks. >> >> Because it makes very hard to understand what's going on and makes no >> sense semantically. >> >>> As you can see, here two arguments are unpacked in one call. >> >> This is very special use case to be hidden in library functions, I don't >> think we need to have language syntax specially directed at that, at the >> cost of making it overall more complex and hard to understand. I can see >> what "add all those params at the end" syntax mean. However having >> something like ($a, ...$b, $c, ...$d, $e, $f, $g, ...$h) I have no idea >> what's going on at all and what is sent where. >> >> > I agree with Stas here. If an argument comes after an unpacked array, its > position is not certain until runtime. This makes life difficult for static > analysis tools, which is one of the reasons for introducing the new syntax.
The alternative is for users to use what we have now: call_user_func_array with some array_merge, which makes it as difficult for static analysis as the new syntax does. This really is a non-argument. And should we really restrict the user's code with some arbitrary limits? It just makes the user use some really ugly hacks nobody wants to see.
> Even in the use case of Nikita, the two arguments to be unpacked come > without any standard arguments between or after them. > > I suggest that argument unpacking should be limited to the last arguments > only.
An example where it really would make sense is: function long ($arg, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $string) { // do something with your arguments } // just instead of copying the seven parameters; increases readability // and don't argue this would be badly statically analyzable - it is, but this isn't // the point. I want to show that people may find here some use case. function short (...$args) { if (count($args)) return long(...$args, "some value"); }
> Lazare Inepologlou > Ingénieur Logiciel > > > > -- >> Stanislav Malyshev, Software Architect >> SugarCRM: http://www.sugarcrm.com/ >> (408)454-6900 ext. 227
I finally am in favor of the proposal, because it allows removing a lot of ugly call_user_func_array calls which aren't really well readable. (and naturally because it allows passing the variadic parameters if that rfc will be accepted) And I think you are really arguing about non-issues. Example: Multiple uses of unpacking syntax makes sense when you call a function with a variadic parameter: function variadic (...$args) { // do something } variadic(...$array1, ...$array2); Bob Weinand

Stas Malyshev

13 years ago
Hi!
> function short (...$args) { > if (count($args)) > return long(...$args, "some value"); > }
This is exactly the problem. Since $args has undefined number of arguments, there's no way to determine where "some value" ends up. Which means it's impossible to understand what's going on here. Now, if we had named arguments, like python had, then using "some value" as a named argument might work (and we'd need to see what to do with named arguments in this case), but as positional argument this just doesn't make much sense beyond some very esoteric things that nobody uses directly, without wrapping libraries (like partially applied functions) - at least in PHP.
> And I think you are really arguing about non-issues. > Example: Multiple uses of unpacking syntax makes sense when you call a > function with a variadic parameter: > > function variadic (...$args) { > // do something > } > > variadic(...$array1, ...$array2);
Again, since parameters in PHP are positional, they have meaning depending on position. If you just wanted to pass an array, pass an array, you don't need to use variadic syntax for that. Variadic syntax makes sense only if positions there have meanings and you want to give specific meanings to specific arguments in specific positions. In that case, ...$array1, ...$array2 doesn't work since you can not have meaningful positions. Only case where it works if you do functional operations like partial application, where the meaning of the function is not important but only the fact that it is a function is important. But I don't think we need special syntax to do such things.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Bob Weinand

13 years ago
Hi! Am 31.8.2013 um 01:39 schrieb Stas Malyshev <smalyshev@sugarcrm.com>:
> Hi! > >> function short (...$args) { >> if (count($args)) >> return long(...$args, "some value"); >> } > > This is exactly the problem. Since $args has undefined number of > arguments, there's no way to determine where "some value" ends up. Which > means it's impossible to understand what's going on here. Now, if we had > named arguments, like python had, then using "some value" as a named > argument might work (and we'd need to see what to do with named > arguments in this case), but as positional argument this just doesn't > make much sense beyond some very esoteric things that nobody uses > directly, without wrapping libraries (like partially applied functions) > - at least in PHP.
That's why there is an if (count($args)) (I just forgot to add an == 7) It should read: function short (...$args) { if (count($args) == 7) return long(...$args, "some value"); } And when you name the example with the "esoteric things", I'd like to have them in the most readable format possible, which isn't achievable with func_get_args().
>> And I think you are really arguing about non-issues. >> Example: Multiple uses of unpacking syntax makes sense when you call a >> function with a variadic parameter: >> >> function variadic (...$args) { >> // do something >> } >> >> variadic(...$array1, ...$array2); > > Again, since parameters in PHP are positional, they have meaning > depending on position. If you just wanted to pass an array, pass an > array, you don't need to use variadic syntax for that. Variadic syntax > makes sense only if positions there have meanings and you want to give > specific meanings to specific arguments in specific positions. In that > case, ...$array1, ...$array2 doesn't work since you can not have > meaningful positions. Only case where it works if you do functional > operations like partial application, where the meaning of the function > is not important but only the fact that it is a function is important. > But I don't think we need special syntax to do such things.
I mean, it looks way cleaner to use this instead of: call_user_func_array("variadic", array_merge($array1, $array2)); And no, the order isn't always important. Example: function variadic (...$args) { return array_reduce($args, function ($a, $b) { return $a*$b; }, 1); } Yes, this is a very simple example, but just to show the idea of it. And even when the order is important, it may be useful: // according to implementation, arrays are expanded in insertion order here // https://github.com/nikic/php-src/compare/variadics...splat#L11R3263 $short_default_options = [ "arg1" => 1, "arg2" => 3, "arg3" => 7, ]; function short (...$extra_options) { global $short_default_options; // in classes, this would be a $this->short_options if (count($args) <= 3) return long(...$short_default_options, ...$extra_options); } function long ($arg1, $arg2, $arg3, $arg4 = 0, $arg5 = 0, $arg6 = 0) { // do something }
> -- > Stanislav Malyshev, Software Architect > SugarCRM: http://www.sugarcrm.com/ > (408)454-6900 ext. 227
Bob Weinand

Lazare Inepologlou

13 years ago
2013/8/31 Bob Weinand <bobwei9@hotmail.com>
> Hi! > > Am 31.8.2013 um 00:27 schrieb Lazare Inepologlou <linepogl@gmail.com>: > > > 2013/8/30 Stas Malyshev <smalyshev@sugarcrm.com> > > > >>> don't see a reason why one should explicitly disallow doing multiple > >>> unpacks. > >> > >> Because it makes very hard to understand what's going on and makes no > >> sense semantically. > >> > >>> As you can see, here two arguments are unpacked in one call. > >> > >> This is very special use case to be hidden in library functions, I don't > >> think we need to have language syntax specially directed at that, at the > >> cost of making it overall more complex and hard to understand. I can see > >> what "add all those params at the end" syntax mean. However having > >> something like ($a, ...$b, $c, ...$d, $e, $f, $g, ...$h) I have no idea > >> what's going on at all and what is sent where. > >> > >> > > I agree with Stas here. If an argument comes after an unpacked array, its > > position is not certain until runtime. This makes life difficult for > static > > analysis tools, which is one of the reasons for introducing the new > syntax. > > The alternative is for users to use what we have now: call_user_func_array > with some array_merge, which makes it as difficult for static analysis as > the > new syntax does. This really is a non-argument. > >
Please read carefully my argument. The alternative is to actually call the function normally with the arguments expanded in the code. In other words, the alternative to this: strpos( ...$array , 3 ); // which cannot be verified statically is this: strpos( $array[0] , $array[1] , 3 ); // which is perfectly verifiable. The power of this proposal is found when used with optional arguments (or variadic arguments) which always come last anyway. Lazare INEPOLOGLOU Ingénieur Logiciel

Bob Weinand

13 years ago
Hi! Am 31.8.2013 um 01:39 schrieb Lazare Inepologlou <linepogl@gmail.com>:
> > > 2013/8/31 Bob Weinand <bobwei9@hotmail.com> > Hi! > > Am 31.8.2013 um 00:27 schrieb Lazare Inepologlou <linepogl@gmail.com>: > > > 2013/8/30 Stas Malyshev <smalyshev@sugarcrm.com> > > > >>> don't see a reason why one should explicitly disallow doing multiple > >>> unpacks. > >> > >> Because it makes very hard to understand what's going on and makes no > >> sense semantically. > >> > >>> As you can see, here two arguments are unpacked in one call. > >> > >> This is very special use case to be hidden in library functions, I don't > >> think we need to have language syntax specially directed at that, at the > >> cost of making it overall more complex and hard to understand. I can see > >> what "add all those params at the end" syntax mean. However having > >> something like ($a, ...$b, $c, ...$d, $e, $f, $g, ...$h) I have no idea > >> what's going on at all and what is sent where. > >> > >> > > I agree with Stas here. If an argument comes after an unpacked array, its > > position is not certain until runtime. This makes life difficult for static > > analysis tools, which is one of the reasons for introducing the new syntax. > > The alternative is for users to use what we have now: call_user_func_array > with some array_merge, which makes it as difficult for static analysis as the > new syntax does. This really is a non-argument. > > > > Please read carefully my argument. The alternative is to actually call the function normally with the arguments expanded in the code. > > In other words, the alternative to this: > strpos( ...$array , 3 ); // which cannot be verified statically > > is this: > strpos( $array[0] , $array[1] , 3 ); // which is perfectly verifiable. > > > The power of this proposal is found when used with optional arguments (or variadic arguments) which always come last anyway. > > > Lazare INEPOLOGLOU > Ingénieur Logiciel
This also isn't anything it ever would write, because it just doesn't make any sense for two or three arguments. In my opinion you only should unpack arrays when it's at the end … AND when you can verify how many parameters will be inserted. Just shorter. Because writing: func($array[0], $array[1], $array[2], $array[3], $array[4], $array[5], $array[6], "value"); is just ugly to write and to read. if (count($array) == 7) func(...$array, "value"); is much more readable, I think. Bob Weinand

Nikita Popov

13 years ago
On Fri, Aug 30, 2013 at 11:50 PM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:
> > If staying consistent with foreach is not wanted (or this is not > How calling a function can be consistent with foreach? Those are > different things. Calling a function should be consistent with all other > cases of calling a function.
Consistent with Traversable error handling. But don't want to argue that, as I do agree with you that adding the exception there may not be a good idea.
> it should work like other instances of non-ref parameter (i.e. not a > variable and not a function returning by ref) passed to by-ref function. > Namely producing E_STRICT.
"Other instances" do everything ranging from fatal error (not a variable) over warning (zend_call_function) to E_STRICT (a function returning by-value). I suggested a warning because I had the general impression that we're trying to be more strict about by-reference passing. But if you're saying that E_STRICT is the right choice here, then lets go with that. I adjusted the RFC/implementation to use E_STRICT instead, see: https://wiki.php.net/rfc/argument_unpacking#by-reference_passing
>>> a = [1]; b = [2] > >>> range(*a, *b) > File "<stdin>", line 1 > range(*a, *b) > ^ > SyntaxError: invalid syntax > > >>> a=[0] > >>> range(*a, 3) > File "<stdin>", line 1 > SyntaxError: only named arguments may follow *expression >
I wasn't aware that Python had such restrictions. I just checked and found out that Ruby also had this restriction, but it was *removed* in version 1.9.1. I couldn't find anything more specific on why they did it though (how Ruby does language development is a mystery to me. I can't even find docs...) The ECMAScript Harmony proposal does not seem to have this restriction. I also tried this in CoffeeScript, which also does not have the restriction.
> > don't see a reason why one should explicitly disallow doing multiple > > unpacks. > > Because it makes very hard to understand what's going on and makes no > sense semantically. > > > As you can see, here two arguments are unpacked in one call. > > This is very special use case to be hidden in library functions, I don't > think we need to have language syntax specially directed at that, at the > cost of making it overall more complex and hard to understand. I can see > what "add all those params at the end" syntax mean. However having > something like ($a, ...$b, $c, ...$d, $e, $f, $g, ...$h) I have no idea > what's going on at all and what is sent where.
It's possible to use nearly *any* feature in some totally convoluted way that nobody can understand. The main usage of the proposed syntax will be just fn(...$args) or fn($some, $fixed, $arguments, ...$args). In rare cases it will be fn(...$args1, ...$args2) [the bind example]. That's what you'll see in code. fn(...$args, $fixed) does not usually make sense, but if it does for once, why do we need to forbid it? If it doesn't make sense, people just won't use it, so you won't see it, so you won't have to figure out what it means. If it does make sense, then understanding it should be trivial. Of course, maybe my logic is flawed because I give too much credit to programmers and assume that they will employ features when reasonable and not when "hey, why don't I go put a ... in here!" Anyway, I don't think having a trailing fixed argument is *that* absurd. A pretty pointless example off the top of my head would be $this->query($query . ' LIMIT ?', ...$params, $limit), i.e. just adding another bound param to a set of existing ones. I don't really insist on allowing the trailing normal args, because I don't think they would be useful particularly often, but I just fail to see what we gain by forbidding them. Thanks, Nikita

Adam Harvey

13 years ago
On 31 August 2013 03:21, Nikita Popov <nikita.ppv@gmail.com> wrote:
>> This is very special use case to be hidden in library functions, I don't >> think we need to have language syntax specially directed at that, at the >> cost of making it overall more complex and hard to understand. I can see >> what "add all those params at the end" syntax mean. However having >> something like ($a, ...$b, $c, ...$d, $e, $f, $g, ...$h) I have no idea >> what's going on at all and what is sent where.
I can grok this, but I'd rather not have to work through it when reading someone else's code. The likely code in current versions of PHP using call_user_func_array() would almost certainly be clearer here. So I think I'd prefer to disallow multiple splats in a function invocation too. <snip>
> Of course, maybe my logic is flawed because I give too much credit to > programmers and assume that they will employ features when reasonable and > not when "hey, why don't I go put a ... in here!"
At the risk of sounding even more bitter than normal, you need to spend more time in ##php with that attitude. ;)
> Anyway, I don't think having a trailing fixed argument is *that* absurd. A > pretty pointless example off the top of my head would be > $this->query($query . ' LIMIT ?', ...$params, $limit), i.e. just adding > another bound param to a set of existing ones. > > I don't really insist on allowing the trailing normal args, because I don't > think they would be useful particularly often, but I just fail to see what > we gain by forbidding them.
I have pretty much the same readability concern as with multiple splats — this example is clear, but I'm not sure it's so clear with a larger, more verbose set of arguments. This seems to require a slightly sharper eye to me (OK, it'd be better in a fixed width editor, admittedly): do_something($a_long_variable, $another_long_variable, ...$hey_a_splat, $something_else, $foo, $bar) I care less about this than multiple splats, but it's still a concern to me. Adam, who will send another e-mail momentarily to paint some bikesheds.

Lazare Inepologlou

13 years ago
2013/8/30 Stas Malyshev <smalyshev@sugarcrm.com>
> Hi! > > > This RFC proposes to add a syntax for argument unpacking: > > > > https://wiki.php.net/rfc/argument_unpacking > > > > Basically, this is the "complement" of the variadics RFC: It is not about > > declaring variadic functions, but about calling them. > > This is just another way of doing call_user_func, I'm not sure we really > need it. And something like: > test(1, 2, ...[3, 4], 5, 6, ...[7, 8]) > > looks plain weird. What would be the use case for doing something like > that? I don't think we should add this. > >
Yes, this example is weird, because every argument is hardcoded anyway. I guess it has been added just for completeness. A good example would be function forwarding for variadic functions, without resorting to call_user_func_array. An even better example is that there would be no need to have both call_user_func and call_user_func_array in the first place: The former would be enough. The same applies to userland functions, and I have been many times in a situation where I had to define two different functions to cover both cases. Lazare INEPOLOGLOU Ingénieur Logiciel

Stas Malyshev

13 years ago
Hi!
> A good example would be function forwarding for variadic functions, > without resorting to call_user_func_array.
What's wrong with "resorting to" call_user_func_array? call_user_func_array is a PHP function and not some dark magic that one should avoid using unless it is absolutely must.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Lazare Inepologlou

13 years ago
2013/8/30 Stas Malyshev <smalyshev@sugarcrm.com>
> Hi! > > > A good example would be function forwarding for variadic functions, > > without resorting to call_user_func_array. > > What's wrong with "resorting to" call_user_func_array? > call_user_func_array is a PHP function and not some dark magic that one > should avoid using unless it is absolutely must. > >
The disadvantages of call_user_func_array are very well described in the RFC. Lazare INEPOLOGLOU Ingénieur Logiciel

Andrey Hristov

13 years ago
On 08/30/2013 05:23 PM, Nikita Popov wrote:
> Hi internals! > > This RFC proposes to add a syntax for argument unpacking: > > https://wiki.php.net/rfc/argument_unpacking > > Basically, this is the "complement" of the variadics RFC: It is not about > declaring variadic functions, but about calling them. > > The syntax it introduces looks as follows: > > $db->query($query, ...$params); > > Thoughts? > > Thanks, > Nikita >
can't we use a new cast operator like (unpack) for this instead of the three dots? $db->query($query, (unpack) $params); ? Andrey

Adam Harvey

13 years ago
On 30 August 2013 08:23, Nikita Popov <nikita.ppv@gmail.com> wrote:
> The syntax it introduces looks as follows: > > $db->query($query, ...$params);
Somebody was going to do this, and it's going to be me. Sorry. We were doing so well. I don't like the ellipsis. I could just about deal with it for the variadic RFC, since it's at least not worlds away from C++ (and there are other precedents for it, as you noted), but it looks really weird to me as the splat operator. It looks like you're hesitant to call the function or ashamed of $params rather than unpacking something. I know there's a symbol soup issue for by-ref variadic arguments, as you mentioned in the RFC, but I think that's an unusual enough use case that * is still the better option — it doesn't break the flow of the code as much as a three character operator, and while it's no more visually intuitive than ..., it does have the advantage of being what Python and Ruby used. I'm raising this in this thread because I'm more concerned about the visual impact of it here, but obviously whatever we use as the operator for one is what we should use for the other, assuming both RFCs are accepted. Adam, who is wincing as he sends this at the likely subthread that will ensue.

Sara Golemon

13 years ago
Big +1 from me, though as Stas pointed out, multiple unpacks in a single call don't really work with PHP parameter typing, so I'd make that use an error. On Sat, Aug 31, 2013 at 10:57 AM, Adam Harvey <aharvey@php.net> wrote:

Pierre Joye

13 years ago
hi Nikita! On Fri, Aug 30, 2013 at 5:23 PM, Nikita Popov <nikita.ppv@gmail.com> wrote:
> Hi internals! > > This RFC proposes to add a syntax for argument unpacking: > > https://wiki.php.net/rfc/argument_unpacking > > Basically, this is the "complement" of the variadics RFC: It is not about > declaring variadic functions, but about calling them. > > The syntax it introduces looks as follows: > > $db->query($query, ...$params); > > Thoughts?
The more I read these two RFCs (and the previous ones about similar features), the more I think we really need to find a compromise about named arguments. Many of the problems (remotely or closely related) would be solved too. About the syntax used in these RFCs, I really have to try out the patch and see if it feels natural, but can't say it while reading the RFCs... :) Cheers,
-- Pierre @pierrejoye | http://www.libgd.org