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
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
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
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
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.
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
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.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
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.
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.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,
BilgeIf 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
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.
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
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