[VOTE] array_key_first(), array_key_last(), array_value_first(), array_value_last()

php.internals

Enno Woortmann

8 years ago
Hi, as the discussion got no new contributions I'd like to start the voting for the RFC fo add new functions for the handling of outer array elements. https://wiki.php.net/rfc/array_key_first_last To have a better separation I split up the vote for the functions. The first vote covers the functions to handle keys: array_key_first() and array_key_last(). The second vote covers the corresponding functions to handle the values: array_value_first() and array_value_last(). As this RFC adds functions but doesn't change the language syntax a 50% + 1 majority is required for both votes. The votes are open until 2018-07-16. The discussion for this RFC is located at https://externals.io/message/102245 Regards, Enno

Levi Morrison

8 years ago
I called for use-cases and practically nobody responds and you put it to vote, discarding nearly all advice you were given? -1

=?utf-8?B?5rGf5rmW5aSn6Jm+5LuB?=

8 years ago
I voted no. I don't think we have an agreement on dealing with non-existing value, and the way this RFC proposed, just returning null without any notice/warning, is wrong IMO. I know we already do this in other array_* functions, but we cannot keep making mistakes just because we already made same mistake. Regards, CHU Zhaowei

Dan Ackroyd

8 years ago
Also voting no, and wished I had mailed earlier. Accessing the keys and values separately is not a good design in my opinion, as it leads to:
> All four functions either return the requested key/value > or null if an empty array is provided.
Having what looks likes valid values returned for array_value_first() and array_value_last() A think a better pattern would be to return a tuple as Levi suggested. [$key, $value] = array_first($array); [$key, $value] = array_last($array); For people not used to returning tuples.....you should branch out a bit and try using them. They are a better pattern to use when returning multiple values from a function that don't need/deserve their own class/struct creating. cheers Dan Ack On 9 July 2018 at 18:31, CHU Zhaowei <me@jhdxr.com> wrote:

Pedro Magalhães

8 years ago
On Mon, Jul 9, 2018 at 6:31 PM CHU Zhaowei <me@jhdxr.com> wrote:
> I don't think we have an agreement on dealing with non-existing value, and > the way this RFC proposed, just returning null without any notice/warning, > is wrong IMO. I know we already do this in other array_* functions, but we > cannot keep making mistakes just because we already made same mistake. >
I voted no for the same reason. I'd even say that introducing a new array_ function that still accepts non arrays just to return null with a warning doesn't make sense at this point. With that said, I'd gladly vote yes if there would be a way to distinguish array_value_first([]) from array_value_first([0 => null]). Regards, Pedro

Levi Morrison

8 years ago
On Tue, Jul 10, 2018 at 12:59 PM Pedro Magalhães <mail@pmmaga.net> wrote:
> > On Mon, Jul 9, 2018 at 6:31 PM CHU Zhaowei <me@jhdxr.com> wrote: > > > I don't think we have an agreement on dealing with non-existing value, and > > the way this RFC proposed, just returning null without any notice/warning, > > is wrong IMO. I know we already do this in other array_* functions, but we > > cannot keep making mistakes just because we already made same mistake. > > > > I voted no for the same reason. I'd even say that introducing a new array_ > function that still accepts non arrays just to return null with a warning > doesn't make sense at this point. > > With that said, I'd gladly vote yes if there would be a way to distinguish > array_value_first([]) from array_value_first([0 => null]). > > Regards, > Pedro
To safely use it a call to empty or count or something needs to happen: if (!empty($array)) { $value = array_value_first($array); // do something with $value } This is okay, but not great. Compare that to the design that returns a tuple though: if ([$_, $value] = array_first($array)) { // do something with $value } People who argue against the tuple because they don't like the design need to consider the bigger picture. The tuple way is less code, serves more use cases with fewer functions, and I even [implemented it][1]. If the array destructuring behavior seems unclear we can simply put an example in the manual pages for these functions -- problem solved. This is not how RFC feedback should be handled. I hope more people vote no so we can reject this do it properly.

Levi Morrison

8 years ago
On Tue, Jul 10, 2018 at 6:41 PM Levi Morrison <levim@php.net> wrote:

Levi Morrison

8 years ago
(Sorry for the duplicate message there, got some hotkeys wrong in my client). Here's the implementation: https://github.com/php/php-src/compare/master...morrisonlevi:array_first-and-array_last

Côme Chilliet

8 years ago
Le mardi 10 juillet 2018, 18:41:17 CEST Levi Morrison a écrit :
> People who argue against the tuple because they don't like the design > need to consider the bigger picture.
My guess is people arguing for the tuple do not understand the usecase :-) Each time I felt the need for array_first_value was because I was using it on a function return to do something with it. Like: if (array_first_value(some_function()) > 3) { // do something } Either I know that the array is not empty, or I do not care because NULL will be ignored correctly. In the second case, with a tuple I’m stuck because if I do: if (array_first(some_function())[1] > 3) { // do something } If array_first returns NULL this will trigger a PHP error. So I have to add more code to handle this special case while I do not need any with array_first_value. Côme

Levi Morrison

8 years ago
> Either I know that the array is not empty, or I do not care because NULL will be ignored correctly. > In the second case, with a tuple I’m stuck because if I do: > > if (array_first(some_function())[1] > 3) { > // do something > } > > If array_first returns NULL this will trigger a PHP error. So I have to add more code to handle this special case while I do not need any with array_first_value.
This is true. For completeness the fix is very mild: if (([$_, $value] = array_first(some_function()) && $value > 3) { // do something } I still think this is better. Forcing you to handle the error case is not a bad thing.

Côme Chilliet

8 years ago
Le mercredi 11 juillet 2018, 07:37:56 CEST Levi Morrison a écrit :
> This is true. For completeness the fix is very mild: > > if (([$_, $value] = array_first(some_function()) && $value > 3) { > // do something > } > > I still think this is better. Forcing you to handle the error case is > not a bad thing.
The point of these functions is to avoid complicated hard to read code for simple operations. This if is hard to read for me and not much better that array_values(some_function())[0]. Côme

Björn Larsson

8 years ago
Den 2018-07-11 kl. 02:41, skrev Levi Morrison:
> On Tue, Jul 10, 2018 at 12:59 PM Pedro Magalhães <mail@pmmaga.net> wrote: >> On Mon, Jul 9, 2018 at 6:31 PM CHU Zhaowei <me@jhdxr.com> wrote: >> >>> I don't think we have an agreement on dealing with non-existing value, and >>> the way this RFC proposed, just returning null without any notice/warning, >>> is wrong IMO. I know we already do this in other array_* functions, but we >>> cannot keep making mistakes just because we already made same mistake. >>> >> I voted no for the same reason. I'd even say that introducing a new array_ >> function that still accepts non arrays just to return null with a warning >> doesn't make sense at this point. >> >> With that said, I'd gladly vote yes if there would be a way to distinguish >> array_value_first([]) from array_value_first([0 => null]). >> >> Regards, >> Pedro > To safely use it a call to empty or count or something needs to happen: > > if (!empty($array)) { > $value = array_value_first($array); > // do something with $value > } > > This is okay, but not great. Compare that to the design that returns a > tuple though: > > if ([$_, $value] = array_first($array)) { > // do something with $value > } > > People who argue against the tuple because they don't like the design > need to consider the bigger picture. The tuple way is less code, > serves more use cases with fewer functions, and I even [implemented > it][1]. If the array destructuring behavior seems unclear we can > simply put an example in the manual pages for these functions -- > problem solved. > > This is not how RFC feedback should be handled. I hope more people > vote no so we can reject this do it properly. >
I do like this approach with two functions array_first & array_last returning a tuple. However, voting is  underway and it looks like it will pass. I wonder what the RFC author (Enno W) thinks about that approach? r//Björn Larsson

Christoph Becker

8 years ago
On 11.07.2018 at 17:19, Björn Larsson wrote:
> Den 2018-07-11 kl. 02:41, skrev Levi Morrison: > >> On Tue, Jul 10, 2018 at 12:59 PM Pedro Magalhães <mail@pmmaga.net> wrote: >> >>> On Mon, Jul 9, 2018 at 6:31 PM CHU Zhaowei <me@jhdxr.com> wrote: >>> >>>> I don't think we have an agreement on dealing with non-existing >>>> value, and >>>> the way this RFC proposed, just returning null without any >>>> notice/warning, >>>> is wrong IMO. I know we already do this in other array_* functions, >>>> but we >>>> cannot keep making mistakes just because we already made same mistake. >>>> >>> I voted no for the same reason. I'd even say that introducing a new >>> array_ >>> function that still accepts non arrays just to return null with a >>> warning >>> doesn't make sense at this point. >>> >>> With that said, I'd gladly vote yes if there would be a way to >>> distinguish >>> array_value_first([]) from array_value_first([0 => null]). >>> >>> Regards, >>> Pedro >> To safely use it a call to empty or count or something needs to happen: >> >>      if (!empty($array)) { >>          $value = array_value_first($array); >>          // do something with $value >>      } >> >> This is okay, but not great. Compare that to the design that returns a >> tuple though: >> >>      if ([$_, $value] = array_first($array)) { >>          // do something with $value >>      } >> >> People who argue against the tuple because they don't like the design >> need to consider the bigger picture. The tuple way is less code, >> serves more use cases with fewer functions, and I even [implemented >> it][1]. If the array destructuring behavior seems unclear we can >> simply put an example in the manual pages for these functions -- >> problem solved. >> >> This is not how RFC feedback should be handled. I hope more people >> vote no so we can reject this do it properly. >> > I do like this approach with two functions array_first & array_last > returning > a tuple. However, voting is  underway and it looks like it will pass. > > I wonder what the RFC author (Enno W) thinks about that approach?
This already has been discussed weeks ago, see <https://externals.io/message/102245#102317>.
-- Christoph M. Becker

Björn Larsson

8 years ago
Den 2018-07-11 kl. 17:27, skrev Christoph M. Becker:
> On 11.07.2018 at 17:19, Björn Larsson wrote: > >> Den 2018-07-11 kl. 02:41, skrev Levi Morrison: >> >>> On Tue, Jul 10, 2018 at 12:59 PM Pedro Magalhães <mail@pmmaga.net> wrote: >>> >>>> On Mon, Jul 9, 2018 at 6:31 PM CHU Zhaowei <me@jhdxr.com> wrote: >>>> >>>>> I don't think we have an agreement on dealing with non-existing >>>>> value, and >>>>> the way this RFC proposed, just returning null without any >>>>> notice/warning, >>>>> is wrong IMO. I know we already do this in other array_* functions, >>>>> but we >>>>> cannot keep making mistakes just because we already made same mistake. >>>>> >>>> I voted no for the same reason. I'd even say that introducing a new >>>> array_ >>>> function that still accepts non arrays just to return null with a >>>> warning >>>> doesn't make sense at this point. >>>> >>>> With that said, I'd gladly vote yes if there would be a way to >>>> distinguish >>>> array_value_first([]) from array_value_first([0 => null]). >>>> >>>> Regards, >>>> Pedro >>> To safely use it a call to empty or count or something needs to happen: >>> >>>      if (!empty($array)) { >>>          $value = array_value_first($array); >>>          // do something with $value >>>      } >>> >>> This is okay, but not great. Compare that to the design that returns a >>> tuple though: >>> >>>      if ([$_, $value] = array_first($array)) { >>>          // do something with $value >>>      } >>> >>> People who argue against the tuple because they don't like the design >>> need to consider the bigger picture. The tuple way is less code, >>> serves more use cases with fewer functions, and I even [implemented >>> it][1]. If the array destructuring behavior seems unclear we can >>> simply put an example in the manual pages for these functions -- >>> problem solved. >>> >>> This is not how RFC feedback should be handled. I hope more people >>> vote no so we can reject this do it properly. >>> >> I do like this approach with two functions array_first & array_last >> returning >> a tuple. However, voting is  underway and it looks like it will pass. >> >> I wonder what the RFC author (Enno W) thinks about that approach? > This already has been discussed weeks ago, see > <https://externals.io/message/102245#102317>. >
Aha, tnx.

Levi Morrison

8 years ago
On Wed, Jul 11, 2018 at 9:27 AM Christoph M. Becker <cmbecker69@gmx.de> wrote:
> > On 11.07.2018 at 17:19, Björn Larsson wrote: > > > Den 2018-07-11 kl. 02:41, skrev Levi Morrison: > > > >> On Tue, Jul 10, 2018 at 12:59 PM Pedro Magalhães <mail@pmmaga.net> wrote: > >> > >>> On Mon, Jul 9, 2018 at 6:31 PM CHU Zhaowei <me@jhdxr.com> wrote: > >>> > >>>> I don't think we have an agreement on dealing with non-existing > >>>> value, and > >>>> the way this RFC proposed, just returning null without any > >>>> notice/warning, > >>>> is wrong IMO. I know we already do this in other array_* functions, > >>>> but we > >>>> cannot keep making mistakes just because we already made same mistake. > >>>> > >>> I voted no for the same reason. I'd even say that introducing a new > >>> array_ > >>> function that still accepts non arrays just to return null with a > >>> warning > >>> doesn't make sense at this point. > >>> > >>> With that said, I'd gladly vote yes if there would be a way to > >>> distinguish > >>> array_value_first([]) from array_value_first([0 => null]). > >>> > >>> Regards, > >>> Pedro > >> To safely use it a call to empty or count or something needs to happen: > >> > >> if (!empty($array)) { > >> $value = array_value_first($array); > >> // do something with $value > >> } > >> > >> This is okay, but not great. Compare that to the design that returns a > >> tuple though: > >> > >> if ([$_, $value] = array_first($array)) { > >> // do something with $value > >> } > >> > >> People who argue against the tuple because they don't like the design > >> need to consider the bigger picture. The tuple way is less code, > >> serves more use cases with fewer functions, and I even [implemented > >> it][1]. If the array destructuring behavior seems unclear we can > >> simply put an example in the manual pages for these functions -- > >> problem solved. > >> > >> This is not how RFC feedback should be handled. I hope more people > >> vote no so we can reject this do it properly. > >> > > I do like this approach with two functions array_first & array_last > > returning > > a tuple. However, voting is underway and it looks like it will pass. > > > > I wonder what the RFC author (Enno W) thinks about that approach? > > This already has been discussed weeks ago, see > <https://externals.io/message/102245#102317>. > > -- > Christoph M. Becker
This was not discussed, it was discarded. Enormous difference.

Levi Morrison

8 years ago
On Wed, Jul 11, 2018 at 10:16 AM Levi Morrison <levim@php.net> wrote:
> > On Wed, Jul 11, 2018 at 9:27 AM Christoph M. Becker <cmbecker69@gmx.de> wrote: > > > > On 11.07.2018 at 17:19, Björn Larsson wrote: > > > > > Den 2018-07-11 kl. 02:41, skrev Levi Morrison: > > > > > >> On Tue, Jul 10, 2018 at 12:59 PM Pedro Magalhães <mail@pmmaga.net> wrote: > > >> > > >>> On Mon, Jul 9, 2018 at 6:31 PM CHU Zhaowei <me@jhdxr.com> wrote: > > >>> > > >>>> I don't think we have an agreement on dealing with non-existing > > >>>> value, and > > >>>> the way this RFC proposed, just returning null without any > > >>>> notice/warning, > > >>>> is wrong IMO. I know we already do this in other array_* functions, > > >>>> but we > > >>>> cannot keep making mistakes just because we already made same mistake. > > >>>> > > >>> I voted no for the same reason. I'd even say that introducing a new > > >>> array_ > > >>> function that still accepts non arrays just to return null with a > > >>> warning > > >>> doesn't make sense at this point. > > >>> > > >>> With that said, I'd gladly vote yes if there would be a way to > > >>> distinguish > > >>> array_value_first([]) from array_value_first([0 => null]). > > >>> > > >>> Regards, > > >>> Pedro > > >> To safely use it a call to empty or count or something needs to happen: > > >> > > >> if (!empty($array)) { > > >> $value = array_value_first($array); > > >> // do something with $value > > >> } > > >> > > >> This is okay, but not great. Compare that to the design that returns a > > >> tuple though: > > >> > > >> if ([$_, $value] = array_first($array)) { > > >> // do something with $value > > >> } > > >> > > >> People who argue against the tuple because they don't like the design > > >> need to consider the bigger picture. The tuple way is less code, > > >> serves more use cases with fewer functions, and I even [implemented > > >> it][1]. If the array destructuring behavior seems unclear we can > > >> simply put an example in the manual pages for these functions -- > > >> problem solved. > > >> > > >> This is not how RFC feedback should be handled. I hope more people > > >> vote no so we can reject this do it properly. > > >> > > > I do like this approach with two functions array_first & array_last > > > returning > > > a tuple. However, voting is underway and it looks like it will pass. > > > > > > I wonder what the RFC author (Enno W) thinks about that approach? > > > > This already has been discussed weeks ago, see > > <https://externals.io/message/102245#102317>. > > > > -- > > Christoph M. Becker > > This was not discussed, it was discarded. Enormous difference.
As an example, it was claimed:
> If I use a function I expect it to give me a return value which I can > use without any further post processing $wantedValue = > fancyFunction($someInput);
But this isn't true even for the array_value_* functions. There must be pre or post processing because of error conditions. This was pointed out by myself and others, but it was still ignored. This is what I mean by discarded, not discussed.

Enno Woortmann

8 years ago
Am 11.07.2018 um 18:20 schrieb Levi Morrison:
> As an example, it was claimed: > >> If I use a function I expect it to give me a return value which I can >> use without any further post processing $wantedValue = >> fancyFunction($someInput); > But this isn't true even for the array_value_* functions. There must > be pre or post processing because of error conditions. This was > pointed out by myself and others, but it was still ignored. > > This is what I mean by discarded, not discussed.
In my eyes being aware of what I put into a function and thus catching non array inputs and empty inputs before differs a lot from post processing return values as it increases the comprehensibility of the code. I also can think of cases where the input format is known and no further checks are required. Additionally the tuple return pattern is not common among the PHP core functions and I don't know many occurences of this pattern in userland PHP code neither at the companies I've worked at nor at open source software/frameworks (correct me if I'm wrong) except the by far outdated old foreach construct with reset() and each(), thus I assume it's not a that common pattern for PHP developers to use it in core functions. As I pointed out during the discussion we should also watch at existing functions with the same problem, differ between a valid return value and an error. Not all of them can be changed to use different return mechanisms like the tuple return pattern (eg. array_pop). Maybe we can instead think about changing Z_PARAM_ARRAY_EX in a later stage to not return null in error cases but instead throw an InvalidArgumentException or something like that (at least for function calls with an empty array for functions which require a filled array, for invalid types maybe a fatal TypeError like it's thrown when a type hinted argument in a userland function is violated is the correct choice). Would be a pretty large BC breaking change but it would be consistent among the array functions. In my opinion neither rejecting the RFC nor changing it to return tuples solves the underlying problem.

Levi Morrison

8 years ago
On Wed, Jul 11, 2018 at 11:42 AM Woortmann, Enno <enno.woortmann@web.de> wrote:
> > Am 11.07.2018 um 18:20 schrieb Levi Morrison: > > > As an example, it was claimed: > > > >> If I use a function I expect it to give me a return value which I can > >> use without any further post processing $wantedValue = > >> fancyFunction($someInput); > > But this isn't true even for the array_value_* functions. There must > > be pre or post processing because of error conditions. This was > > pointed out by myself and others, but it was still ignored. > > > > This is what I mean by discarded, not discussed. > > In my eyes being aware of what I put into a function and thus catching > non array inputs and empty inputs before differs a lot from post > processing return values as it increases the comprehensibility of the > code. I also can think of cases where the input format is known and no > further checks are required. > > Additionally the tuple return pattern is not common among the PHP core > functions and I don't know many occurences of this pattern in userland > PHP code neither at the companies I've worked at nor at open source > software/frameworks (correct me if I'm wrong) except the by far outdated > old foreach construct with reset() and each(), thus I assume it's not a > that common pattern for PHP developers to use it in core functions. > > As I pointed out during the discussion we should also watch at existing > functions with the same problem, differ between a valid return value and > an error. > Not all of them can be changed to use different return mechanisms like > the tuple return pattern (eg. array_pop). > > Maybe we can instead think about changing Z_PARAM_ARRAY_EX in a later > stage to not return null in error cases but instead throw an > InvalidArgumentException or something like that (at least for function > calls with an empty array for functions which require a filled array, > for invalid types maybe a fatal TypeError like it's thrown when a type > hinted argument in a userland function is violated is the correct > choice). Would be a pretty large BC breaking change but it would be > consistent among the array functions. > > In my opinion neither rejecting the RFC nor changing it to return tuples > solves the underlying problem.
What is the underlying problem in your opinion? My opinion is that the core problem is that these functions cannot be efficiently implemented in userland, at least not the ones that get the last key and/or value of the array. You either need to make a copy or traverse through the whole array. I have been working to solve this by making a bidirectional array iterator that can start at either end of the array and can traverse back and forth. This work will not ready for 7.3, not even with the extension to the feature freeze because there is some design that needs to happen; the work I have so far is here: https://github.com/php/php-src/compare/master...morrisonlevi:BidirectionalArrayIterator

Christoph Becker

8 years ago
On 11.07.2018 at 18:16, Levi Morrison wrote:
> On Wed, Jul 11, 2018 at 9:27 AM Christoph M. Becker <cmbecker69@gmx.de> wrote: >> >> On 11.07.2018 at 17:19, Björn Larsson wrote: >> >>> I do like this approach with two functions array_first & array_last >>> returning >>> a tuple. However, voting is underway and it looks like it will pass. >>> >>> I wonder what the RFC author (Enno W) thinks about that approach? >> >> This already has been discussed weeks ago, see >> <https://externals.io/message/102245#102317>. > > This was not discussed, it was discarded. Enormous difference.
Well, there was some discussion. Particularly noteworthy, was Rowan's post[1] which pointed out that the behavior of list is *undocumented*, and Larry's post[2] which strongly advises against “multi-returns”. And finally, as I understand it, the actual proposal that is put to vote is what the RFC *author* wants to propose. There is no strict necessity to deal with any suggestion for improvement. After all, it's up to the voters whether a particular RFC will be accepted or rejected. If anybody dislikes a certain RFC, they are free to point out their concerns, and to vote against the RFC. Period. [1] <https://externals.io/message/102245#102326> [2] <https://externals.io/message/102245#102326>
-- Christoph M. Becker

Colin O'Dell

8 years ago
On Tue, Jul 10, 2018 at 8:42 PM Levi Morrison <levim@php.net> wrote:
> This is not how RFC feedback should be handled. I hope more people > vote no so we can reject this do it properly. >
I agree with the spirit of this RFC but I also agree with Levi. It feels like this particular implementation is being rushed through without properly addressing some of the outstanding issues and alternate implementation ideas that have been raised. The only revisions to the RFC were the inclusion of the two value-related functions. IMHO, any RFC going to vote despite known "opposition" or requested changes should at least contain a summary of those points and counter-points, but if feels like those are being ignored here. So while I do understand the value of such a feature, I'd much rather delay its implementation than to rush it along with potential issues and no strong consensus. Respectfully, Colin O'Dell colinodell@gmail.com https://www.colinodell.com

Niklas Keller

8 years ago
Hey, any reason for not having both, resulting in a total of 6 functions? Regards, Niklas

Andrew Faulds

8 years ago
Hi, CHU Zhaowei wrote:
> I voted no. > I don't think we have an agreement on dealing with non-existing value, and the way this RFC proposed, just returning null without any notice/warning, is wrong IMO. I know we already do this in other array_* functions, but we cannot keep making mistakes just because we already made same mistake. > > Regards, > CHU Zhaowei >
Hmm. Returning null with no warning makes perfect sense for keys, since null is not a valid key so there's no ambiguity, but for values it seems problematic. On that ground I've decided to change my vote to No for the value functions, but keep the vote for Yes for the key functions. Someone who wants such behaviour could always do ($array[array_key_last($array)] ?? null), I guess.
-- Andrea Faulds https://ajf.me/

Côme Chilliet

8 years ago
Le jeudi 12 juillet 2018, 01:04:36 CEST Andrea Faulds a écrit :
> Hmm. Returning null with no warning makes perfect sense for keys, since > null is not a valid key so there's no ambiguity, but for values it seems > problematic. On that ground I've decided to change my vote to No for the > value functions, but keep the vote for Yes for the key functions. > Someone who wants such behaviour could always do > ($array[array_key_last($array)] ?? null), I guess.
You cannot do that easily if the array is returned by a function. function()[array_key_last(function())] would call the function twice.

Christoph Becker

8 years ago
On 12.07.2018 at 09:06, Côme Chilliet wrote:
> Le jeudi 12 juillet 2018, 01:04:36 CEST Andrea Faulds a écrit : > >> Hmm. Returning null with no warning makes perfect sense for keys, since >> null is not a valid key so there's no ambiguity, but for values it seems >> problematic. On that ground I've decided to change my vote to No for the >> value functions, but keep the vote for Yes for the key functions. >> Someone who wants such behaviour could always do >> ($array[array_key_last($array)] ?? null), I guess.
Ditto!
> You cannot do that easily if the array is returned by a function. > function()[array_key_last(function())] would call the function twice.
You can easily store the function's return value in a variable, though.
-- Christoph M. Becker

Yasuo Ohgaki

8 years ago
On Thu, Jul 12, 2018 at 8:05 AM Andrea Faulds <ajf@ajf.me> wrote:
> Hi, > > CHU Zhaowei wrote: > > I voted no. > > I don't think we have an agreement on dealing with non-existing value, > and the way this RFC proposed, just returning null without any > notice/warning, is wrong IMO. I know we already do this in other array_* > functions, but we cannot keep making mistakes just because we already made > same mistake. > > > > Regards, > > CHU Zhaowei > > >
Since PHP supports null coalesce, it makes sense applying null coalesce by default. Many users do it for inputs. e.g $var = $_GET['var'] ?? null;
> > Hmm. Returning null with no warning makes perfect sense for keys, since > null is not a valid key so there's no ambiguity, but for values it seems > problematic. On that ground I've decided to change my vote to No for the > value functions, but keep the vote for Yes for the key functions. > Someone who wants such behaviour could always do > ($array[array_key_last($array)] ?? null), I guess. >
When array_value_last($array) is needed, users would want null coalesce almost always. When user don't want it, they can if (array_key_last($array) === NULL) { // Or if (!count($array)) { die("hey, no value defined"); } $var = array_value_last($array); This usage would be rare and use of ($array[array_key_last($array)] ?? null) for null coalesce is pain. It lacks API consistency as well. Therefore, I voted "yes" for both. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Levi Morrison

8 years ago
Not sure what timezone you are in; current votes are: Add array_key_first() and array_key_last()? - Yes (19) - No (13) Add array_value_first() and array_value_last()? - Yes (16) - No (17) The first vote will pass with 59.375%. The second fails at ~48.48%.

Levi Morrison

8 years ago
On Mon, Jul 9, 2018 at 5:17 AM Woortmann, Enno <enno.woortmann@web.de> wrote:
> > Hi, > > as the discussion got no new contributions I'd like to start the voting > for the RFC fo add new functions for the handling of outer array elements. > > https://wiki.php.net/rfc/array_key_first_last > > To have a better separation I split up the vote for the functions. The > first vote covers the functions to handle keys: array_key_first() and > array_key_last(). The second vote covers the corresponding functions to > handle the values: array_value_first() and array_value_last(). > > As this RFC adds functions but doesn't change the language syntax a 50% > + 1 majority is required for both votes. The votes are open until > 2018-07-16. > > The discussion for this RFC is located at > > https://externals.io/message/102245 > > Regards, > > Enno > > > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php
This entire time I felt like this should be possible in pure PHP. Surely, somewhere, we have this capability already? I searched quite a few functions but didn't find anything. However, the feeling was right. Just moments ago Paul Crovella from Stack Overflow mentioned to me that `array_slice` uses the terminology `offset` to refer to the order of the entry rather than its key, so I went looking. As far as I can tell from the [array_slice implementation][1] it will not trigger copies and will be efficient if using -1 to retrieve the last index. We can provide the parameter `preserve_keys` an argument of true to get both the key and the value. These functions *are* efficiently implementable in user-land! Below is a proof-of-concept for the `array_offset` function [mentioned by Nicolas Grekas][2] (which by the way, neither the RFC author nor anyone else responded to this suggestion) that is simply a convenience wrapper over `array_slice`: function array_offset(array $input, int $offset): ?array { $slice = array_slice($input, $offset, 1, true); return count($slice) ? $slice : null; } $assoc = ['one' => 1, 'two' => 2, 'three' => 3]; $packd = range(1, 4); var_dump(array_offset($assoc, -1)); var_dump(array_offset($packd, -1)); var_dump(array_offset($assoc, 0)); var_dump(array_offset($packd, 0)); Of course, the `array_slice` function can be used to build all of the functions described in the RFC, as well. My new opinion is that no new functions are required and that improving the `array_slice` documentation is all that is necessary. It currently does not show any examples of it working on associated arrays, which is probably why none of us (many of us experts) realized this through this discussion. This is especially true as "offset" in some other situations really means "key", as in `ArrayAccess::offsetGet`. [1]: https://github.com/php/php-src/blob/b9963969fd088dca6852483fdb1c6b7e1080764d/ext/standard/array.c#L3477-L3577 [2]: https://externals.io/message/102245#102322

Levi Morrison

8 years ago
On Fri, Jul 13, 2018 at 4:48 PM Levi Morrison <levim@php.net> wrote:
> > On Mon, Jul 9, 2018 at 5:17 AM Woortmann, Enno <enno.woortmann@web.de> wrote: > > > > Hi, > > > > as the discussion got no new contributions I'd like to start the voting > > for the RFC fo add new functions for the handling of outer array elements. > > > > https://wiki.php.net/rfc/array_key_first_last > > > > To have a better separation I split up the vote for the functions. The > > first vote covers the functions to handle keys: array_key_first() and > > array_key_last(). The second vote covers the corresponding functions to > > handle the values: array_value_first() and array_value_last(). > > > > As this RFC adds functions but doesn't change the language syntax a 50% > > + 1 majority is required for both votes. The votes are open until > > 2018-07-16. > > > > The discussion for this RFC is located at > > > > https://externals.io/message/102245 > > > > Regards, > > > > Enno > > > > > > > > > > -- > > PHP Internals - PHP Runtime Development Mailing List > > To unsubscribe, visit: http://www.php.net/unsub.php > > This entire time I felt like this should be possible in pure PHP. > Surely, somewhere, we have this capability already? I searched quite a > few functions but didn't find anything. > > However, the feeling was right. Just moments ago Paul Crovella from > Stack Overflow mentioned to me that `array_slice` uses the terminology > `offset` to refer to the order of the entry rather than its key, so I > went looking. As far as I can tell from the [array_slice > implementation][1] it will not trigger copies and will be efficient if > using -1 to retrieve the last index. We can provide the parameter > `preserve_keys` an argument of true to get both the key and the value. > These functions *are* efficiently implementable in user-land! > > Below is a proof-of-concept for the `array_offset` function [mentioned > by Nicolas Grekas][2] (which by the way, neither the RFC author nor > anyone else responded to this suggestion) that is simply a convenience > wrapper over `array_slice`: > > function array_offset(array $input, int $offset): ?array { > $slice = array_slice($input, $offset, 1, true); > return count($slice) ? $slice : null; > } > > $assoc = ['one' => 1, 'two' => 2, 'three' => 3]; > $packd = range(1, 4); > > var_dump(array_offset($assoc, -1)); > var_dump(array_offset($packd, -1)); > > var_dump(array_offset($assoc, 0)); > var_dump(array_offset($packd, 0)); > > Of course, the `array_slice` function can be used to build all of the > functions described in the RFC, as well. > > My new opinion is that no new functions are required and that > improving the `array_slice` documentation is all that is necessary. It > currently does not show any examples of it working on associated > arrays, which is probably why none of us (many of us experts) realized > this through this discussion. This is especially true as "offset" in > some other situations really means "key", as in > `ArrayAccess::offsetGet`. > > [1]: https://github.com/php/php-src/blob/b9963969fd088dca6852483fdb1c6b7e1080764d/ext/standard/array.c#L3477-L3577 > [2]: https://externals.io/message/102245#102322
Small correction: Nicolas used the name `array_index`, not `array_offset`.

Levi Morrison

8 years ago
On Fri, Jul 13, 2018 at 4:50 PM Levi Morrison <levim@php.net> wrote:
> > On Fri, Jul 13, 2018 at 4:48 PM Levi Morrison <levim@php.net> wrote: > > > > On Mon, Jul 9, 2018 at 5:17 AM Woortmann, Enno <enno.woortmann@web.de> wrote: > > > > > > Hi, > > > > > > as the discussion got no new contributions I'd like to start the voting > > > for the RFC fo add new functions for the handling of outer array elements. > > > > > > https://wiki.php.net/rfc/array_key_first_last > > > > > > To have a better separation I split up the vote for the functions. The > > > first vote covers the functions to handle keys: array_key_first() and > > > array_key_last(). The second vote covers the corresponding functions to > > > handle the values: array_value_first() and array_value_last(). > > > > > > As this RFC adds functions but doesn't change the language syntax a 50% > > > + 1 majority is required for both votes. The votes are open until > > > 2018-07-16. > > > > > > The discussion for this RFC is located at > > > > > > https://externals.io/message/102245 > > > > > > Regards, > > > > > > Enno > > > > > > > > > > > > > > > -- > > > PHP Internals - PHP Runtime Development Mailing List > > > To unsubscribe, visit: http://www.php.net/unsub.php > > > > This entire time I felt like this should be possible in pure PHP. > > Surely, somewhere, we have this capability already? I searched quite a > > few functions but didn't find anything. > > > > However, the feeling was right. Just moments ago Paul Crovella from > > Stack Overflow mentioned to me that `array_slice` uses the terminology > > `offset` to refer to the order of the entry rather than its key, so I > > went looking. As far as I can tell from the [array_slice > > implementation][1] it will not trigger copies and will be efficient if > > using -1 to retrieve the last index. We can provide the parameter > > `preserve_keys` an argument of true to get both the key and the value. > > These functions *are* efficiently implementable in user-land! > > > > Below is a proof-of-concept for the `array_offset` function [mentioned > > by Nicolas Grekas][2] (which by the way, neither the RFC author nor > > anyone else responded to this suggestion) that is simply a convenience > > wrapper over `array_slice`: > > > > function array_offset(array $input, int $offset): ?array { > > $slice = array_slice($input, $offset, 1, true); > > return count($slice) ? $slice : null; > > } > > > > $assoc = ['one' => 1, 'two' => 2, 'three' => 3]; > > $packd = range(1, 4); > > > > var_dump(array_offset($assoc, -1)); > > var_dump(array_offset($packd, -1)); > > > > var_dump(array_offset($assoc, 0)); > > var_dump(array_offset($packd, 0)); > > > > Of course, the `array_slice` function can be used to build all of the > > functions described in the RFC, as well. > > > > My new opinion is that no new functions are required and that > > improving the `array_slice` documentation is all that is necessary. It > > currently does not show any examples of it working on associated > > arrays, which is probably why none of us (many of us experts) realized > > this through this discussion. This is especially true as "offset" in > > some other situations really means "key", as in > > `ArrayAccess::offsetGet`. > > > > [1]: https://github.com/php/php-src/blob/b9963969fd088dca6852483fdb1c6b7e1080764d/ext/standard/array.c#L3477-L3577 > > [2]: https://externals.io/message/102245#102322 > > Small correction: Nicolas used the name `array_index`, not `array_offset`.
Unfortunately I was too hasty: `array_slice` will iterate over the entire input range: https://github.com/php/php-src/blob/b9963969fd088dca6852483fdb1c6b7e1080764d/ext/standard/array.c#L3538-L3552 We could add an case for when `array_slice` uses `-1`. I wonder how common this already is. Does anyone have a tool that easily can search open source code for usages of functions? I am interested in this regardless of the outcome of this RFC. The documentation for `array_slice` should also be updated independently of this RFC as well.

Marcos Passos

8 years ago
A function like array_offset would be convenient as there is no way to access the value of an array entry by its index currently. The workaround is using array_slice, with all the downsides already pointed out. 2018-07-13 20:04 GMT-03:00 Levi Morrison <levim@php.net>:

Côme Chilliet

8 years ago
Le vendredi 13 juillet 2018, 16:48:29 CEST Levi Morrison a écrit :
> Below is a proof-of-concept for the `array_offset` function [mentioned > by Nicolas Grekas][2] (which by the way, neither the RFC author nor > anyone else responded to this suggestion) that is simply a convenience > wrapper over `array_slice`: > > function array_offset(array $input, int $offset): ?array { > $slice = array_slice($input, $offset, 1, true); > return count($slice) ? $slice : null; > } > > $assoc = ['one' => 1, 'two' => 2, 'three' => 3]; > $packd = range(1, 4); > > var_dump(array_offset($assoc, -1)); > var_dump(array_offset($packd, -1)); > > var_dump(array_offset($assoc, 0)); > var_dump(array_offset($packd, 0)); > > Of course, the `array_slice` function can be used to build all of the > functions described in the RFC, as well.
How would you do that, since array_slice still gives you an associative array as a result? array_values(array_slice($array, -1, 1, true))[0] is way less readable than array_last_value($array), and the question «how efficient is that and how many array copies are made?» becomes complicated to answer for non-initiated. While with a native function you expect it to be as efficient as possible to do what you ask it. (And as you state in your other mail in the end this array_slice solution is not as efficient as you expected) I would have been fine with array_key($array, $offset=0) and array_value($array, $offset=0) instead of the 4 functions from the RFC to be able to use any offset. Côme

Enno Woortmann

8 years ago
Am 09.07.2018 um 13:16 schrieb Woortmann, Enno:
> Hi, > > as the discussion got no new contributions I'd like to start the > voting for the RFC fo add new functions for the handling of outer > array elements. > > https://wiki.php.net/rfc/array_key_first_last > > To have a better separation I split up the vote for the functions. The > first vote covers the functions to handle keys: array_key_first() and > array_key_last(). The second vote covers the corresponding functions > to handle the values: array_value_first() and array_value_last(). > > As this RFC adds functions but doesn't change the language syntax a > 50% + 1 majority is required for both votes. The votes are open until > 2018-07-16. > > The discussion for this RFC is located at > > https://externals.io/message/102245 > > Regards, > > Enno
Hello together, The vote for this RFC has been closed. The vote for the initially RFC containing the functions array_key_first() and array_key_last() was accepted, the vote for the extended RFC (adding also array_value_first() and array_value_last()) was declined. I'll update the pull request located at https://github.com/php/php-src/pull/3256 tomorrow and remove the array_value functions as well as adopt the code review remarks of derickr so the PR can be merged for PHP 7.3. Thanks for the participation, Enno

Christoph Becker

8 years ago
On 17.07.2018 at 01:13, Enno Woortmann wrote:
> Am 09.07.2018 um 13:16 schrieb Woortmann, Enno: > >> https://wiki.php.net/rfc/array_key_first_last > > The vote for this RFC has been closed. The vote for the initially RFC > containing the functions array_key_first() and array_key_last() was > accepted, the vote for the extended RFC (adding also array_value_first() > and array_value_last()) was declined.
When time permits, please update the RFC to state that it has been implemented for PHP 7.3.0 via commit 50516a6[1], and link to the manual pages[2] (which should be online tomorrow). [1] <http://git.php.net/?p=php-src.git;a=commit;h=50516a6> [2] <http://php.net/manual/en/function.array-key-first.php> <http://php.net/manual/en/function.array-key-last.php>
-- Christoph M. Becker