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
Thanks,
-John
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.
Thanks for submitting this RFC! I am +1, with one quibble: obtaining the
value by reference seems non-sequitur to the function itself and PHP in
general. IOW, this seems more PHPesque to me:
// get the next to last value
$key = array_key_index($arr, -2);
$val = $arr[$key];
Sincerely,
bishop
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.
Thanks for submitting this RFC! I am +1, with one quibble: obtaining the value by reference seems non-sequitur to the function itself and PHP in general. IOW, this seems more PHPesque to me:
// get the next to last value
$key = array_key_index($arr, -2);
$val = $arr[$key];Sincerely,
bishop
While relatively rare for PHP, these aren't the only functions that have an optional second return value by reference. (preg_match, preg_replace, str_replace, among others.)
I agree that that’s a bit unusual in terms of PHP, but, if you actually need both the key and the value, this way you can do it in one call, rather than having to access the array and pull the value out of it separately. The C code already has a reference to the hashtable bucket, so returning the value if it’s needed is trivial.
-John
Hi John,
Thanks for submitting the RFC. It just has one piece of something that I
feel needs a bit of refinement.
The balance of the $key and the $val is out of sync, with one param being
by-val and one by-ref.
You could simplify the function to remove the &$val altogether, since the
function name is about getting the key. Less is more here.
I know you pointed out examples of other unusual functions, but we must
live with those things historically for BC reasons. Given the opportunity
to get it right I'd like to propose removal of &$val so the function does
what its name says.
Thus it would look like this:
$val = $array[array_key_last($array)];
Many thanks,
Paul
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.Thanks for submitting this RFC! I am +1, with one quibble: obtaining
the value by reference seems non-sequitur to the function itself and PHP in
general. IOW, this seems more PHPesque to me:// get the next to last value
$key = array_key_index($arr, -2);
$val = $arr[$key];Sincerely,
bishopWhile relatively rare for PHP, these aren't the only functions that have
an optional second return value by reference. (preg_match, preg_replace,
str_replace, among others.)I agree that that’s a bit unusual in terms of PHP, but, if you actually
need both the key and the value, this way you can do it in one call, rather
than having to access the array and pull the value out of it separately.
The C code already has a reference to the hashtable bucket, so returning
the value if it’s needed is trivial.-John
Thus it would look like this:
$val = $array[array_key_last($array)];
Or how about a matching set of array_value_* functions?
Granted, we can currently use reset()
and last() for array_value_first()
and array_value_last(), but that always feels a bit ugly to me. The name
"reset" is hardly obvious, and the side-effects of "resetting the
internal array pointer" even less so (e.g. how does it affect
copy-on-write?).
Regards,
--
Rowan Collins
[IMSoP]
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 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.
Thanks.
Andrea Faulds
https://ajf.me/
Hi Andrea,
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/347How 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
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.
Personally, I think they would be very handy, if accompanied by
array_value_first and array_value_last. The "ordered hash" PHP provides
is a very powerful structure, but sometimes you just want to peek at one
or other end of the array without any side effects, and it feels weird
that there's no neat idiomatic way of doing this.
Incidentally, the ability to define the functions in userland is quite a
positive - it means they can be polyfilled and codebases can start
making use of them without requiring a major version bump.
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 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.
This argument does seem reasonable - I can't think of many situations
where you'd want exactly one key or element, at a known position, in an
indexed array. And as soon as you want two keys or elements, you're
probably better off using array_keys / array_values to give you a list
which can be efficiently randomly accessed.
Regards,
--
Rowan Collins
[IMSoP]