[RFC] Allow specifying keys in list()

php.internals

Andrew Faulds

10 years ago
Hi everyone, Here's an RFC that would extend the syntax of list() to be more useful with associative arrays: https://wiki.php.net/rfc/list_keys Please read it and tell me your thoughts. Thanks!
-- Andrea Faulds https://ajf.me/

Bishop Bettini

10 years ago
On Sat, Jan 16, 2016 at 9:32 PM, Andrea Faulds <ajf@ajf.me> wrote:
> Hi everyone, > > Here's an RFC that would extend the syntax of list() to be more useful > with associative arrays: > > https://wiki.php.net/rfc/list_keys > > Please read it and tell me your thoughts. >
Nice, Andrea, thanks! Destructuring is quite handy. I wonder if there is opportunity to include array gathering. Something along the lines of: list ('foo' => $foo, ...$rest) = [ 'foo' => 1, 'bar' => 2, 'baz' => 3]; assert $foo === 1; assert $rest === [ 'bar' => 2, 'baz' => 3]; What do you think?

Andrew Faulds

10 years ago
Hi Bishop, Bishop Bettini wrote:
> On Sat, Jan 16, 2016 at 9:32 PM, Andrea Faulds <ajf@ajf.me> wrote: > >> Hi everyone, >> >> Here's an RFC that would extend the syntax of list() to be more useful >> with associative arrays: >> >> https://wiki.php.net/rfc/list_keys >> >> Please read it and tell me your thoughts. >> > > Nice, Andrea, thanks! Destructuring is quite handy. > > I wonder if there is opportunity to include array gathering. Something > along the lines of: > > list ('foo' => $foo, ...$rest) = [ 'foo' => 1, 'bar' => 2, 'baz' => 3]; > assert $foo === 1; > assert $rest === [ 'bar' => 2, 'baz' => 3]; > > What do you think?
That might be useful, and it's certainly intuitive. In languages with linked lists like Haskell, you can pattern-match the rest of a list, so there's a precedent. Though with linked lists it's an O(1) operation, while this is O(n). I don't think that should go into this RFC specifically, though, but it could be a future enhancement. Thanks!
-- Andrea Faulds https://ajf.me/

Pierre Joye

10 years ago
hi Andrea, I very much like this proposal. Good work as usual! The only part where I think we should not rely on list is the future scope. I can see the logic that leads to use list for named arguments. However I really think it is a very different topic and having to use list to define arguments, it sounds like a hack to solve another long due feature. Anyway, as it is not part of this RFC, I will ignore it for now :) Keep the good work, Cheers, Pierre On Mon, Jan 18, 2016 at 9:07 AM, Andrea Faulds <ajf@ajf.me> wrote:
> Hi Bishop, > > > Bishop Bettini wrote: >> >> On Sat, Jan 16, 2016 at 9:32 PM, Andrea Faulds <ajf@ajf.me> wrote: >> >>> Hi everyone, >>> >>> Here's an RFC that would extend the syntax of list() to be more useful >>> with associative arrays: >>> >>> https://wiki.php.net/rfc/list_keys >>> >>> Please read it and tell me your thoughts. >>> >> >> Nice, Andrea, thanks! Destructuring is quite handy. >> >> I wonder if there is opportunity to include array gathering. Something >> along the lines of: >> >> list ('foo' => $foo, ...$rest) = [ 'foo' => 1, 'bar' => 2, 'baz' => 3]; >> assert $foo === 1; >> assert $rest === [ 'bar' => 2, 'baz' => 3]; >> >> What do you think? > > > That might be useful, and it's certainly intuitive. In languages with linked > lists like Haskell, you can pattern-match the rest of a list, so there's a > precedent. Though with linked lists it's an O(1) operation, while this is > O(n). > > I don't think that should go into this RFC specifically, though, but it > could be a future enhancement. > > > Thanks! > -- > Andrea Faulds > https://ajf.me/ > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
-- Pierre @pierrejoye | http://www.libgd.org

Robert Stoll

10 years ago
Hi Andrea I am writing you in private since I think this is rather out of scope. -----Ursprüngliche Nachricht-----
> Von: Pierre Joye [mailto:pierre.php@gmail.com] > Gesendet: Montag, 18. Januar 2016 05:54 > An: Andrea Faulds > Cc: PHP internals > Betreff: Re: [PHP-DEV] [RFC] Allow specifying keys in list() > > hi Andrea, > > I very much like this proposal. Good work as usual! > > The only part where I think we should not rely on list is the future scope. I can see the logic that leads to use list for named > arguments. > However I really think it is a very different topic and having to use list to define arguments, it sounds like a hack to solve > another long due feature.
I agree with Pierre on this one. Using list for named parameters seems like a lot of overhead on the declaration side to me (writing the name of a parameter twice). IMO it should not require additional effort than writing a function/method today and it should be available for all functions/methods and not only for ones with special named-paramater-syntax. I think you should consider further (when thinking about using the new feature for named parameters) - how can you specify optional parameters? - how can you specify byRef parameters? - what happens if one does not provide all keys? Currently this: list($a, $b) = [1]; //only produces a Warning - are there differences between strict mode and none strict mode? e.g., what if the type of the key is different? - would it be possible to use a type for the key as well (as for the value indicated in your RFC)? - would you allow nested destructuring for parameters? - how would you reduce the overhead of creating an array which is then copied and passed to the function? IMO destructuring parameters and named parameters are two different things which could be combined. Something like this: function foo(SomeClass $class, list("x" => $x, "y" => $y) $point = ["x"=>0, "y"=>0], $flagA = true, $flagB = 1) { } foo($myClass, point: [1,2], flagB: 0); foo($myClass, flagB: 2); yet, IMO it would hamper readability (probably in many cases) and it would be better to do it inside the function. I understand destructuring parameters just as syntactic sugar and I would still expect that PhpDocumenter would indicate that my function requires an array. Otherwise the same feature would suddenly also be used to declare deep structured data structures and at this point I am not so sure whether auto conversion of keys play well together with strict mode. It would certainly be interesting from a type safety point of view that one can define very complex data structures and let PHP do the work for verification. Yet, it also opens a door to very ugly code (well... which also exists without the feature) -- sorry, drifting away from the topic. Some other points crossing my mind - how well does the feature interact with typed arrays (if they should be introduced at some point)? - how well does it interact with structural types (if they should be introduced at some point)? And now some points to the RFC: - I like the RFC in general - I am not really a fan of the naming "list" in general but I think it is appropriate to reuse the same syntax for this task. - one thing I am missing in the RFC is error handling. What happens if a key is not found? And there are surely other questions. I think you should include a section about error handling in the RFC. - I guess mixing number keys with string keys is possible, right? - are placeholders (something like list(_ , $a, _) = [1,2,3]) in your pipeline or do you think they make no sense in PHP? - already an idea how it would interact with pattern matching? Cheers, Robert

Unnamed Person

10 years ago
Hi Robert, for named parameters, I would prefer this syntax over list(): function foo($foo, [a: string $a, b: int &$b, c: bool $c = true]) { ... work with $foo, $a, $b, $c } $b = 42; foo('foo', ['a' => 'bar', 'b' => $b]); function bar($foo, SomeClass {a: string $a, b: int &$b, c: bool $c = true}) { ... work with $foo, $a, $b, $c } $o = new SomeClass(); $o->a = 'bar'; $o->b = 42; bar('foo', $o); Regards Thomas Robert Stoll wrote on 20.01.2016 22:20:

Michael Wallner

10 years ago
On 17/01/16 03:32, Andrea Faulds wrote:
> Hi everyone, > > Here's an RFC that would extend the syntax of list() to be more useful > with associative arrays: > > https://wiki.php.net/rfc/list_keys > > Please read it and tell me your thoughts.
Hi! I found the idea convincing from the first read, but maybe it's just my mind's assumptions about list() that I dislike the resulting syntax, yet, it seems to be the logical choice. So, maybe I'm just trying to say, that I don't like list() to be reused for that, but I don't have any better idea otherwise.
-- Regards, Mike

Lester Caine

10 years ago
On 18/01/16 07:19, Michael Wallner wrote:
>> Here's an RFC that would extend the syntax of list() to be more useful >> > with associative arrays: >> > >> > https://wiki.php.net/rfc/list_keys >> > >> > Please read it and tell me your thoughts. > Hi! > > I found the idea convincing from the first read, but maybe it's just my > mind's assumptions about list() that I dislike the resulting syntax, > yet, it seems to be the logical choice. > > So, maybe I'm just trying to say, that I don't like list() to be reused > for that, but I don't have any better idea otherwise.
As someone still using 'extract' in legacy code, I can sort of see the logistics of this, but why not just extend 'extract' to use the current object rather than the symbol table. It already has handling for duplicate keys and to prefix the 'array' name to the resulting variables.
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Rowan Collins

10 years ago
Lester Caine wrote on 18/01/2016 12:35:
> As someone still using 'extract' in legacy code, I can sort of see the > logistics of this, but why not just extend 'extract' to use the current > object rather than the symbol table. It already has handling for > duplicate keys and to prefix the 'array' name to the resulting variables.
The main advantage I can see is that this is a whitelist-based approach - you state explicitly in your code what you expect the array to look like, and what variables you are assigning based on it. This is very different from "whatever's in this array, turn it into a variable". The "current object" was just one possible use case, have a look at some of the other examples in the RFC, such as: list( CURLOPT_GET => $isGet, CURLOPT_POST => $isPost, CURLOPT_URL => $url ) = $curlOptions; Note that $curlOptions probably had other things in it, $url may be an existing variable getting a new value. The best extract would give you is $curloption_10002, which isn't all that useful. Regards,
-- Rowan Collins [IMSoP]

Leigh

10 years ago
On 18 January 2016 at 12:35, Lester Caine <lester@lsces.co.uk> wrote:
> > Hi! > > > > I found the idea convincing from the first read, but maybe it's just my > > mind's assumptions about list() that I dislike the resulting syntax, > > yet, it seems to be the logical choice. > > > > So, maybe I'm just trying to say, that I don't like list() to be reused > > for that, but I don't have any better idea otherwise. > > As someone still using 'extract' in legacy code, I can sort of see the > logistics of this, but why not just extend 'extract' to use the current > object rather than the symbol table. It already has handling for > duplicate keys and to prefix the 'array' name to the resulting variables.
The uses for this extended syntax go beyond simply populating object properties, and shoehorning it into extract would pretty much limit it to this use-case. In favour of this improvement, although I would very much like to see variable keys too (second option makes the most sense to me, as it's in line with the syntax). How feasible would it be to add an exception to mixed keys? I'm thinking list(7 => $a, $b, $c, $d) to specify an initial offset, similar to how you can define an array as [7 => 0, 1, 2, 3]. This obviously goes hand in hand with my desire for variable keys :) Thanks Andrea, looking forward to this.

Alex Sky

10 years ago
> How feasible would it be to add an exception to mixed keys? I'm thinking > list(7 => $a, $b, $c, $d) to specify an initial offset, similar to how you > can define an array as [7 => 0, 1, 2, 3]. This obviously goes hand in hand > with my desire for variable keys :)
I would like it to be like, destructuring assignment, in ES6 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Andrew Faulds

10 years ago
Hi Leigh, Leigh wrote:
> > The uses for this extended syntax go beyond simply populating object > properties, and shoehorning it into extract would pretty much limit it to > this use-case. >
In fact I don't think extract() even works on object properties. list() works with any "variable" (in the isset() sense). I should really add some more examples to the RFC, so that it's more obvious that $this-> assignment is not the only thing this can or will be used for.
> In favour of this improvement, although I would very much like to see > variable keys too (second option makes the most sense to me, as it's in > line with the syntax).
So far I haven't actually heard anyone say they thought it would behave like (1), which is making me think that allowing arbitrary expressions would be fine. It'd be unfortunate to lock them out, because constants can't contain objects, so now you wouldn't be able to use list() with SplObjectStorage and such, and that would be a shame. (2) is the only thing I was going to make it do anyway, (1) would mean list() functioning differently than it does at present.
> How feasible would it be to add an exception to mixed keys? I'm thinking > list(7 => $a, $b, $c, $d) to specify an initial offset, similar to how you > can define an array as [7 => 0, 1, 2, 3]. This obviously goes hand in hand > with my desire for variable keys :)
Oh, yeah, it's unfortunate that what the RFC currently proposes makes using initial offsets not possible. :/ The main reason I ended up disallowing mixed keys was because it complicates implementation if you have a some value that must be computed at runtime as a key (some constants, a variable, etc.), because now we can't hard-code the indexes of the following values into the opcodes. We don't know at compile-time that it'll be 5, 6, 7, we know it'll be $x, *maybe* $x + 1 (if $x was an index, otherwise it'll be the previous index), *maybe* $x + 2, etc. The problem with disallowing mixed keys is it's inconsistent with the array literal syntax, and as you've demonstrated, it also is inconvenient for some use cases. As implemented, keyed list() is actually an entirely different parser branch from unkeyed list(). It's all a bit too arbitrary. I may just have to allow mixed keys after all, even if it does make implementation a pain. I could add an exception for a leading offset, but that would have to have its own special rules. Better to just do things properly.
> > Thanks Andrea, looking forward to this. >
I'm glad you like it!
-- Andrea Faulds https://ajf.me/

Andrew Faulds

10 years ago
Hi again, Andrea Faulds wrote:
>> How feasible would it be to add an exception to mixed keys? I'm thinking >> list(7 => $a, $b, $c, $d) to specify an initial offset, similar to how >> you >> can define an array as [7 => 0, 1, 2, 3]. This obviously goes hand in >> hand >> with my desire for variable keys :) > > Oh, yeah, it's unfortunate that what the RFC currently proposes makes > using initial offsets not possible. :/ > > The main reason I ended up disallowing mixed keys was because it > complicates implementation if you have a some value that must be > computed at runtime as a key (some constants, a variable, etc.), because > now we can't hard-code the indexes of the following values into the > opcodes. We don't know at compile-time that it'll be 5, 6, 7, we know > it'll be $x, *maybe* $x + 1 (if $x was an index, otherwise it'll be the > previous index), *maybe* $x + 2, etc. > > The problem with disallowing mixed keys is it's inconsistent with the > array literal syntax, and as you've demonstrated, it also is > inconvenient for some use cases. As implemented, keyed list() is > actually an entirely different parser branch from unkeyed list(). It's > all a bit too arbitrary. > > I may just have to allow mixed keys after all, even if it does make > implementation a pain. I could add an exception for a leading offset, > but that would have to have its own special rules. Better to just do > things properly.
After considering how to implement this at the opcode level, I've decided again that it's not worth it. Mixing keyed and unkeyed elements is not only an implementation nuisance (it's not necessarily hard, but it makes things more complicated), it's not something likely to be used in practice, and I think it's probably an indicator of bad code. Now, I can understand your case, but I don't really want to add a special exception for it. If we're allowing keyed or unkeyed, not both, then we should stick to it. Also, I realised that in your case (`list(7 => $a, $b, $c, $d)`), there are other, possibly cleaner ways to do it, such as: list($a, $b, $c, $d) = array_slice($array, 7); This way is simple and clear. It's probably clearer than `list(7 => $a, $b, $c, $d)` in fact. There's also this: list(($i = 7) => $a, ++$i => $b, ++$i => $c, ++$i => $d) = $array; This way is horrible, but at least demonstrates there are other ways to achieve what you want. Thanks!
-- Andrea Faulds https://ajf.me/

Leigh

10 years ago
On 19 January 2016 at 02:20, Andrea Faulds <ajf@ajf.me> wrote:
> After considering how to implement this at the opcode level, I've decided > again that it's not worth it. Mixing keyed and unkeyed elements is not only > an implementation nuisance (it's not necessarily hard, but it makes things > more complicated), it's not something likely to be used in practice, and I > think it's probably an indicator of bad code. > > Now, I can understand your case, but I don't really want to add a special > exception for it. If we're allowing keyed or unkeyed, not both, then we > should stick to it. > > Also, I realised that in your case (`list(7 => $a, $b, $c, $d)`), there are > other, possibly cleaner ways to do it, such as: > > list($a, $b, $c, $d) = array_slice($array, 7); > > This way is simple and clear. It's probably clearer than `list(7 => $a, $b, > $c, $d)` in fact. There's also this: > > list(($i = 7) => $a, ++$i => $b, ++$i => $c, ++$i => $d) = $array; > > This way is horrible, but at least demonstrates there are other ways to > achieve what you want.
Thanks, I wouldn't worry about it. The use-case was hypothetical anyway. I could see how I might use it, but I have nowhere at present I'd actually use it. list($offset => $a, $b, $b, $c) = $array; $offset += 4; vs. list($a, $b, $c, $d) = array_slice($array, $offset); $offset += 4; Probably not worth the complexity overhead as you suggest, for what amounts to (arguably) syntactic sugar. I also doubt it would see enough usage to warrant the small gain of avoiding the fcall there.

Andrew Faulds

10 years ago
Hi again, I've updated the RFC to v1.1, because I've resolved the open issue of whether to allow arbitrary expressions for keys. It seems that the risk of confusion was less than I thought it was, and allowing anything not only simplifies implementation, but means you can do things like have object keys (when working with SplObjectStorage, for example). You may wish to look over the RFC again: https://wiki.php.net/rfc/list_keys Thanks.
-- Andrea Faulds https://ajf.me/

Stas Malyshev

10 years ago
Hi!
> Here's an RFC that would extend the syntax of list() to be more useful > with associative arrays: > > https://wiki.php.net/rfc/list_keys > > Please read it and tell me your thoughts.
After reading the RFC, it looks like a great idea. I wouldn't exactly encourage this for replacement of named parameters (for one, I understand it would produce some complaints - like notice? - if the key does not exist) but there are cases when it's useful and I don't see any harm in it.
-- Stas Malyshev smalyshev@gmail.com