array_reduce callback key

php.internals

Bilge

2 years ago
Hi Internals, I just ran into a case where I needed the array key in an array_reduce() callback, but I can't access it :( So I wrote a PR to fix it: https://github.com/php/php-src/pull/14986 What do you think? Does this need an RFC? Cheers, Bilge

mickmackusa

2 years ago
This is not the first time that a developer needs access to the input array's keys within the callback of array_reduce(). It is untrue that you "can't access it"; you just need to use an array of keys as the input array. Some frameworks already have the feature of key access built into their methods/functions. https://laravel.com/docs/11.x/collections#method-reduce Examples of passing array_keys to array_reduce (some of which are more than a decade old): https://stackoverflow.com/a/10196070/2943403 https://stackoverflow.com/a/27419768/2943403 https://stackoverflow.com/a/27809675/2943403 https://stackoverflow.com/a/32226816/2943403 https://stackoverflow.com/a/33372066/2943403 https://stackoverflow.com/a/37728665/2943403 https://stackoverflow.com/a/39322532/2943403 https://stackoverflow.com/a/45508817/2943403 https://stackoverflow.com/a/48664250/2943403 https://stackoverflow.com/a/49035053/2943403 https://stackoverflow.com/a/57966850/2943403 https://stackoverflow.com/a/58997848/2943403 https://stackoverflow.com/a/73726419/2943403 https://stackoverflow.com/a/76196482/2943403 mickmackusa On Wed, 17 Jul 2024, 09:15 Bilge, <bilge@scriptfusion.com> wrote:

Bilge

2 years ago
On Wed, 17 Jul 2024, 01:29 mickmackusa, <mickmackusa@gmail.com> wrote:
> It is untrue that you "can't access it"; you just need to use an array of > keys as the input array. > >> It is absolutely true and your workaround is just that; a workaround that
doesn't work at all when you also need the value. Cheers, Bilge

Lily Bergonzat

2 years ago
While it *is* indeed a workaround, you can very easily access the values of the array from the keys, since that literally is what the keys are for. While I also think it's weird that not all php array functions with callbacks do pass the key as an argument, and while I also stumbled upon that problem in the past myself multiple times, I also think it is worth taking the time to consider what other people from this mailing list are bringing up. If it could indeed break internal callbacks, then I think using the workaround could be a better idea than potentially breaking other things. On Wed, Jul 17, 2024 at 2:38 AM Bilge <bilge@scriptfusion.com> wrote:

Rob Landers

2 years ago
On Wed, Jul 17, 2024, at 09:55, Lily Bergonzat wrote:
> While it *is* indeed a workaround, you can very easily > access the values of the array from the keys, since that > literally is what the keys are for. > > While I also think it's weird that not all php array functions > with callbacks do pass the key as an argument, and while > I also stumbled upon that problem in the past myself > multiple times, I also think it is worth taking the time to > consider what other people from this mailing list are > bringing up. If it could indeed break internal callbacks, > then I think using the workaround could be a better idea > than potentially breaking other things. > > On Wed, Jul 17, 2024 at 2:38 AM Bilge <bilge@scriptfusion.com> wrote: > > > > On Wed, 17 Jul 2024, 01:29 mickmackusa, <mickmackusa@gmail.com> wrote: > >> > >> It is untrue that you "can't access it"; you just need to use an array of keys as the input array. > > > > It is absolutely true and your workaround is just that; a workaround that doesn't work at all when you also need the value. > > > > Cheers, > > Bilge >
If it can be the last argument, then PHP doesn't care if you call a function with extra arguments ... at least, it usually doesn't. — Rob

Lily Bergonzat

2 years ago
It would make sense for it to be the last argument. My first thought was also that PHP doesn't usually care if you add extra arguments, but "internal callbacks" made me think they were C callbacks, and in that case I don't really know. On Wed, Jul 17, 2024 at 10:08 AM Rob Landers <rob@bottled.codes> wrote:

Levi Morrison

2 years ago
On Tue, Jul 16, 2024 at 5:17 PM Bilge <bilge@scriptfusion.com> wrote:
> > Hi Internals, > > I just ran into a case where I needed the array key in an array_reduce() > callback, but I can't access it :( > > So I wrote a PR to fix it: https://github.com/php/php-src/pull/14986 > > What do you think? Does this need an RFC? > > Cheers, > Bilge
I don't think it's reasonable to cover every use-case "nicely" in the standard library. You didn't give a real example. You might consider using array_walk or iterator_apply, or a foreach loop depending on what you need. I am curious what your real use-case is. It may be worth adding something. It might not. Hard to tell. Adding arguments to a function can mess up internal callbacks, btw, so I don't like modifying the existing function.

Bilge

2 years ago
On 17/07/2024 01:41, Levi Morrison wrote:
> Adding arguments to a function can mess up internal callbacks, btw, so I don't like modifying the > existing function.
Which internal callbacks can be messed up by this change? They clearly aren't tested, as the build is passing. Cheers, Bilge

Larry Garfield

2 years ago
On Wed, Jul 17, 2024, at 9:01 AM, Bilge wrote:
> On 17/07/2024 01:41, Levi Morrison wrote: >> Adding arguments to a function can mess up internal callbacks, btw, so I don't like modifying the >> existing function. > Which internal callbacks can be messed up by this change? They clearly > aren't tested, as the build is passing. > > Cheers, > Bilge
There's a number of issues here. PHP-defined functions ignore excess arguments. C-defined functions error on excess arguments. A function with an optional second argument... may break if it gets passed an optional argument that isn't aligned with its expectation. intval() is the usual example (https://www.php.net/intval), but it would also impact something like trim(). If someone is using a function with one param and one optional param as a callback right now, suddenly passing the key as the second argument could cause all sorts of weirdness. Similarly, if someone is using a single-param C-defined function as a callback right now, and array_reduce() starts passing a second argument, it will fatal. I ran into this issue while building Crell/fp, and my only solution (after swearing a lot) was to just make two separate versions of every operation: One that passes the key and one that doesn't. (cf: https://github.com/Crell/fp/blob/master/src/array.php) The user has to pick the right one. That is, sadly, the only reliable solution, even if done in the stdlib. (Of course, the real solution is to introduce a separate map/dict type that has its own dedicated API for map/filter/reduce, but now we're well out of scope... Using the same structure for lists and maps is PHP's original sin.) --Larry Garfield