Re: Re: [RFC] array_key_(first|last|index) functions proposal
| From: | John Bafford | Date: | Mon, 04 Jan 2016 18:34:10 +0000 |
| Subject: | Re: Re: [RFC] array_key_(first|last|index) functions proposal | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-89997@lists.php.net to get a copy of this message | ||
Hi Andrea,
> On Jan 4, 2016, at 12:05, Andrea Faulds <ajf@ajf.me> wrote:
>
> Hi John,
>
> John Bafford wrote:
>> Happy New Year, everyone!
>>
>> I’d like to present the first new PHP RFC for this year, a proposal to add functions to
>> easily get the first, last, or an arbitrary key (and value) by index from an array, taking advantage
>> of PHP’s property that arrays are ordered maps.
>>
>> RFC: https://wiki.php.net/rfc/array_key_first_last_index
>> PR: https://github.com/php/php-src/pull/347
>
> How often would such functions be useful? Perhaps they fill a gap, but I'm not sure if
> it's one that needs filling. array_key_first and array_key_last can already be accomplished in
> two or so lines of code (four if you make a function), and array_key_index can be implemented in a
> few lines with a foreach() loop and a counter.
array_key_first() and array_key_last() can’t be implemented in userspace and maintain all three of
fast, immutable, and doesn’t-look-weird.
The best you could do for array_key_first() is:
function array_key_first($arr) {
foreach($arr as $k => $v)
return $k;
return null;
}
Which already looks kind of weird. For array_key_last, your best bet is
function array_key_last($arr) {
$k = null;
foreach($arr as $k => $v)
;
//Rely on the fall-through of $k from the last iteration
return $k;
}
which looks even weirder
or
function array_key_last($arr) {
$keys = array_keys($arr);
if($cnt = count($keys))
return $keys[$cnt - 1];
return null;
}
Which adds the overhead of array_keys() iterating over the array and duplicating *all* of the
array’s keys just to retrieve one.
Any solution that uses reset() + key() or end() + key() mutates the array, which means duplicating
it if you pass it into a function. This takes a non-trivial time if you have a large array.
> array_key_first and array_key_last seem mostly harmless, at least. I'm not sure the same
> can be said for array_key_index, since it has O(n) complexity. I worry that it might end up used by
> people who think it is more efficient than iterating through an array, even though it is not. I
> would rather we not include this specific function, and avoid potentially disguising the time
> complexity of key lookup, especially as I can't think of a good use-case for it. As for
> array_key_first and array_key_last, well, maybe they're useful, I have no strong opinion on
> them. They might be handy to get the first and last key of an array without moving the internal
> pointer, so who knows, maybe we should add them.
I’ll admit that array_key_index() could be easily abused. If you need to use it more than a few
times on a particular array, unless you’ve got a huge array and need to keep memory use
constrained, you’re probably better off just calling array_keys() and using an index into the
result. This would need to be included in the documentation as a use case caveat, though it
wouldn’t be surprising if people ignored the warning and used it incorrectly anyway.
The reason array_key_index() is included in the RFC is because it kind of fell out of the original
implementation and since it’s kind of useful, for a limited set of problems, I kept it in. It’s
really more of a special-case tool with (very) limited general use, but it is a substantial
improvement over the alternatives if you really do it need.
My primary goal with this RFC is array_key_first() and array_key_last(), so I would not be against
having array_key_index() be a separate voting choice, if that would make people more comfortable.
> Thanks.
> --
> Andrea Faulds
> https://ajf.me/
-John