Hello internals,
I've changed the status of the currently introduced RFC to add the
functions array_key_first() and array_key_last() to "Under Discussion".
https://wiki.php.net/rfc/array_key_first_last
Regards,
Enno
I've changed the status of the currently introduced RFC to add the
functions array_key_first() and array_key_last() to "Under Discussion".
Thanks for working on this, Enno!
I suggest to address Côme's suggestion[1] on this mailing list and
especially in the RFC (the template[2] offers “Open Issues” and
“Rejected Features” sections).
[1] https://externals.io/message/102225#102232
--
Christoph M. Becker
Hi,
I suggest to address Côme's suggestion[1] on this mailing list and
especially in the RFC (the template[2] offers “Open Issues” and
“Rejected Features” sections).
I've added the "Open Issues" section to the RFC and added the idea of Côme and Gabriel to add the corresponding functions for handling the values of the outer elements of an array to provide a complete set of functions.
Currently I see three possibilities to handle the idea. Either extend the scope of the RFC to cover also the handling of the values, which could be implemented rather fast and by reusing a lot of code as the current implementation already gathers the bucket for the first/last element of an array, or move this idea to a future scope which should be covered by a separate RFC. The third alternative would be to skip the implementation of the corresponding functions.
In my opinion it's a good idea to complete the function set by also providing functions for the handling of array values. Both opportunities which would lead to the completed set are practicable in my view.
Any opinions concerning this issue?
Good night (or day, wherever you are ;) ),
Enno
Hello internals,
I've added the "Open Issues" section to the RFC and added the idea of
Côme and Gabriel to add the corresponding functions for handling the
values of the outer elements of an array to provide a complete set of
functions.
Currently I see three possibilities to handle the idea. Either extend
the scope of the RFC to cover also the handling of the values, which
could be implemented rather fast and by reusing a lot of code as the
current implementation already gathers the bucket for the first/last
element of an array, or move this idea to a future scope which should
be covered by a separate RFC. The third alternative would be to skip
the implementation of the corresponding functions.In my opinion it's a good idea to complete the function set by also
providing functions for the handling of array values. Both
opportunities which would lead to the completed set are practicable in
my view.
I've extended the scope of the RFC to cover additionally the functions
array_value_first($array) and array_value_last($array).
The updated RFC is still available at
https://wiki.php.net/rfc/array_key_first_last
https://deref-web-02.de/mail/client/3lM0ZbRqSMo/dereferrer/?redirectUrl=https%3A%2F%2Fwiki.php.net%2Frfc%2Farray_key_first_last
I've added a commit to the pull request located at
https://github.com/php/php-src/pull/3256
https://deref-web-02.de/mail/client/bEY-xQctqjI/dereferrer/?redirectUrl=https%3A%2F%2Fgithub.com%2Fphp%2Fphp-src%2Fpull%2F3256 to
add the implementation and the tests for the extended scope.
Regards,
Enno
Hello internals,
I've changed the status of the currently introduced RFC to add the
functions array_key_first() and array_key_last() to "Under Discussion".https://wiki.php.net/rfc/array_key_first_last
Regards,
Enno
What is the behaviour if the array does not exist? From the current RFC
it appears it would return null? Wouldn't it be better to return false
for this situation?
Niel
Hi niel,
On 15.06.2018 at 17:37 niel wrote:
What is the behaviour if the array does not exist? From the current
RFC it appears it would return null? Wouldn't it be better to return
false for this situation?
Thanks for the comment. Why do you think false would be a better return
value?
Currently if the given value isn't an array or no parameter is given a
warning will be thrown and null will be returned.
In my opinion null exists to show the absence of a defined value. If one
of the proposed functions is called with a variable which isn't an array
or an empty array (or even a call with no parameter) there is neither a
first nor a last key and thus null is the value which is returned.
Compare the tests for the error cases:
https://github.com/php/php-src/pull/3256/files#diff-e00a584724b997f38e851e15f1e20c39
This behavior is also implemented in existing functions like eg.
array_pop()
:
https://github.com/php/php-src/blob/master/ext/standard/tests/array/array_pop_errors.phpt
Enno
Hello internals,
I've changed the status of the currently introduced RFC to add the
functions array_key_first() and array_key_last() to "Under Discussion".https://wiki.php.net/rfc/array_key_first_last
Regards,
Enno
What is the behaviour if the array does not exist? From the current RFC
it appears it would return null? Wouldn't it be better to return false
for this situation?
I don't like throwing false when something doesn't exist.
apcu does that - returns false instead of null when a record doesn't
exist, and it is very problematic when the stored value literally is false.
granted a boolean can't be used for an array key, but still, if there
isn't something to return than null is better than a boolean.
boolean is a value, null is the absence of a value, which is more
accurate, no?
Hi Alice,
Am 17.06.2018 um 22:16 schrieb Alice Wonder:
boolean is a value, null is the absence of a value, which is more
accurate, no?
In my opinion that's the argument to return null for either parameters
which aren't an array or empty arrays simply because a first/last key
isn't present and null is the value to be returned for an undefined state.
I've tested this behavior with other array_* functions which are
provided in the PHP core and they provide null consistently, eg.:
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r "var_dump(array_keys(1));"
PHP Warning: array_keys()
expects parameter 1 to be array, integer
given in Command line code on line 1
NULL
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r
"var_dump(array_values('hello'));"
PHP Warning: array_values()
expects parameter 1 to be array, string
given in Command line code on line 1
NULL
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r "var_dump(array_flip(null));"
PHP Warning: array_flip()
expects parameter 1 to be array, null given
in Command line code on line 1
NULL
There was another remark which wasn't sent to the internals mail list
but to my personal mail account (mehh :( ) which supported to return false:
"because a lot of functions act the way returning false when things go
wrong even when they normally only would return string/int/array which
should be justification enough: consistency"
An example for this argument was the function strpos which may be
checked with === or !== against false.
But the real discussion about the return value and the facility of
comparison against another value is only interesting if we extend the
scope of this RFC to cover also array_value_(first|last), as null as an
array key is not supported and will be casted to an empty string. Due to
this internal handling of array keys, null is for the functions
array_key(first|last) an unique return value to evaluate failures.
My opinion about this subject supports your argument as null is the
value which should be returned if the requested value is not defined. If
a variable which is neither an array nor an array with entries is passed
neither the first/last key nor the first/last value is a defined value
and thus null should be the return value.
Especially if we decide to extend the scope of this RFC to cover also
array_value_(first|last) there is no possibility to provide a return
value which doesn't collide with a possible array value. If cases occur
which may resolve into a collision, the usage of functions like
is_array()
and empty()/count() is inevitable as both null and false are
valid values for an array value. To argument with the semantic of false
and null the correct return value should be null for each of the
proposed functions (as well the proposed functions which are currently
covered by the RFC as the extended version which also covers the methody
array_value(first|last) ) as null defines an undefined value.
Regards,
Enno
Hi Alice,
Am 17.06.2018 um 22:16 schrieb Alice Wonder:
boolean is a value, null is the absence of a value, which is more
accurate, no?In my opinion that's the argument to return null for either parameters
which aren't an array or empty arrays simply because a first/last key
isn't present and null is the value to be returned for an undefined state.
I've tested this behavior with other array_* functions which are
provided in the PHP core and they provide null consistently, eg.:root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r "var_dump(array_keys(1));"
PHP Warning:array_keys()
expects parameter 1 to be array, integer
given in Command line code on line 1
NULL
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r
"var_dump(array_values('hello'));"
PHP Warning:array_values()
expects parameter 1 to be array, string
given in Command line code on line 1
NULL
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r "var_dump(array_flip(null));"
PHP Warning:array_flip()
expects parameter 1 to be array, null given
in Command line code on line 1
NULL
There was another remark which wasn't sent to the internals mail list
but to my personal mail account (mehh :( ) which supported to return false:"because a lot of functions act the way returning false when things go
wrong even when they normally only would return string/int/array which
should be justification enough: consistency"An example for this argument was the function strpos which may be
checked with === or !== against false.
But the real discussion about the return value and the facility of
comparison against another value is only interesting if we extend the
scope of this RFC to cover also array_value_(first|last), as null as an
array key is not supported and will be casted to an empty string. Due to
this internal handling of array keys, null is for the functions
array_key(first|last) an unique return value to evaluate failures.My opinion about this subject supports your argument as null is the
value which should be returned if the requested value is not defined. If
a variable which is neither an array nor an array with entries is passed
neither the first/last key nor the first/last value is a defined value
and thus null should be the return value.Especially if we decide to extend the scope of this RFC to cover also
array_value_(first|last) there is no possibility to provide a return
value which doesn't collide with a possible array value. If cases occur
which may resolve into a collision, the usage of functions like
is_array()
and empty()/count() is inevitable as both null and false are
valid values for an array value. To argument with the semantic of false
and null the correct return value should be null for each of the
proposed functions (as well the proposed functions which are currently
covered by the RFC as the extended version which also covers the methody
array_value(first|last) ) as null defines an undefined value.Regards,
Enno
Hi, I didn't reply to your question as to why I thought false would be a
better return value for non-array, as I thought Reindl covered my
feelings completely.
Given the points made by Alice and yourself I've reconsidered 'false'
being a better choice than 'null', as it might be a valid return value
from the array.
However my main concern that a non-array variable or a non-existent
value, are an error and need to be handled appropriately, has not
changed. IMO, a notice/warning does little to nothing in helping the
programmer determine the problem and track down the cause. Which leaves
one having to wrap these functions in 'if (is_array($var) &&
!empty($var)) {...}' to prevent the possibility.
Niel
Hi niel,
Am 18.06.2018 um 01:59 schrieb niel:
However my main concern that a non-array variable or a non-existent
value, are an error and need to be handled appropriately, has not
changed. IMO, a notice/warning does little to nothing in helping the
programmer determine the problem and track down the cause. Which
leaves one having to wrap these functions in 'if (is_array($var) &&
!empty($var)) {...}' to prevent the possibility.
The current implementation is eqivalent to the other array_* functions
as shown in the previous mail and can be checked in
https://github.com/php/php-src/pull/3256/commits/ec2332be93272d202a2a5cef841c266f77f64b08#diff-e00a584724b997f38e851e15f1e20c39
I can comprehend your doubts about the return value but currently I
can't imagine a solution which would suite the case better than null
especially if we think about extending the scope to
array_value_(first|last).
Do you/anyone have an idea how we can provide better information towards
the programmer to determine the issue?
Enno
In my opinion that's the argument to return null for either parameters
which aren't an array or empty arrays simply because a first/last key
isn't present and null is the value to be returned for an undefined state.
I've tested this behavior with other array_* functions which are
provided in the PHP core and they provide null consistently, eg.:root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r "var_dump(array_keys(1));"
PHP Warning:array_keys()
expects parameter 1 to be array, integer
given in Command line code on line 1
NULL
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r
"var_dump(array_values('hello'));"
PHP Warning:array_values()
expects parameter 1 to be array, string
given in Command line code on line 1
NULL
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r "var_dump(array_flip(null));"
PHP Warning:array_flip()
expects parameter 1 to be array, null given
in Command line code on line 1
NULL
These return values are due to zend_parse_parameters() failures (i.e.
the given types don't match the expected types), and it's customary to
return NULL
in this case (under strict typing an exception would be
thrown instead). However, most functions signal other failures by
returning FALSE, for instance:
var_dump(array_search('foo', [])); // => bool(false)
I would prefer, if these other functions would return NULL, though, but
we can't change that for BC reasons.
--
Christoph M. Becker
In my opinion that's the argument to return null for either parameters
which aren't an array or empty arrays simply because a first/last key
isn't present and null is the value to be returned for an undefined state.
I've tested this behavior with other array_* functions which are
provided in the PHP core and they provide null consistently, eg.:root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r "var_dump(array_keys(1));"
PHP Warning:array_keys()
expects parameter 1 to be array, integer
given in Command line code on line 1
NULL
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r
"var_dump(array_values('hello'));"
PHP Warning:array_values()
expects parameter 1 to be array, string
given in Command line code on line 1
NULL
root@WOL-Soft-DEVVM:/var/www/WOL-Soft# php -r
"var_dump(array_flip(null));"
PHP Warning:array_flip()
expects parameter 1 to be array, null given
in Command line code on line 1
NULL
These return values are due to zend_parse_parameters() failures (i.e.
the given types don't match the expected types), and it's customary to
returnNULL
in this case (under strict typing an exception would be
thrown instead). However, most functions signal other failures by
returning FALSE, for instance:var_dump(array_search('foo', [])); // => bool(false)
I would prefer, if these other functions would return NULL, though, but
we can't change that for BC reasons.
Returning false for "not found" rather than "null" is a big middle-finger to
users. :-) Besides the reasons here, the violation of type constraints
totally screws up the surrounding code. Especially with null-coalesce. For
instance, this thing of beauty:
$secret = getenv('APP_SECRET')
?? $_SERVER['APP_SECRET']
?? getenv('DEFAULT_SECRET')
;
doesn't actually work, because getenv()
returns false instead of null.
Instead you have to do this mess:
$secret = (getenv('APP_SECRET') ?: null)
?? $_SERVER['APP_SECRET']
?? (getenv('DEFAULT_SECRET') ?: null)
;
See also:
https://www.garfieldtech.com/blog/empty-return-values
Can we please never return false for error/not-found, ever, period, forever
more? It's a fundamentally broken idiom that needs to die.
--Larry Garfield
Can we please never return false for error/not-found, ever, period, forever
more? It's a fundamentally broken idiom that needs to die.
“But wait!” some cry. “What about consistency with existing functions?”
--
Christoph M. Becker
I don't think I'm getting all the mail I am supposed to. I hope this gets seen.
I propose 2 functions only which I believe covers the use-cases that
all 4 of these do and more, with shorter names, and the ability to
discern whether the call succeeded or not.
list($key, $value) = array_first($input);
// $key will be null if the call failed
list($key, $value) = array_last($input);
// $key will be null if the call failed
I have tested it with user-land functions and seems to work as
intended in all success and failure conditions. Verification that it
works as intended with internal functions is necessary but this seems
a much better proposal to me.
Hi Levi,
Am 20.06.2018 um 04:47 schrieb Levi Morrison:
list($key, $value) = array_first($input); // $key will be null if the call failed list($key, $value) = array_last($input); // $key will be null if the call failed
Your proposed functions would be implementable with the internal
functions but I think this approach doesn't provide a clean function
interface as it forces the user to evaluate the wanted value from the
returned array structure by using either the list() construct or
something like $key = array_first($input)[0];
I believe two functions with this interface will be confusing and less
intuitive for the developer.
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);
Enno
Hi Levi,
Am 20.06.2018 um 04:47 schrieb Levi Morrison:
list($key, $value) = array_first($input); // $key will be null if the call failed list($key, $value) = array_last($input); // $key will be null if the call failed
Your proposed functions would be implementable with the internal
functions but I think this approach doesn't provide a clean function
interface as it forces the user to evaluate the wanted value from the
returned array structure by using either the list() construct or
something like $key = array_first($input)[0];I believe two functions with this interface will be confusing and less
intuitive for the developer.
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);
Your wish cannot be granted for array_value_last
and
array_value_first
; you cannot know by itself if there is a failure
condition. As proposed you have to write:
if (!empty($input)) {
$value = array_value_last($input)
// do something
}
This is not "clean". In contrast here is with my proposal:
if ([$key, $value] = array_last($input) {
// do something
}
If I need the last/first key and value (which is a real use-case and
why I thought of this in the first place) then in your proposal I have
to do:
if (!empty($input)) {
$key = array_key_last($input);
$value = array_value_last($input);
}
Or use the key to get the value; roughly the same amount of code.
Either way is not as clean as:
if ([$key, $value] = array_last($input) {
// do something
}
Hopefully I have shown that for various use-cases the proposed
interface is cleaner and that you cannot argue against it on those
grounds.
Adding 4 functions which cover 4 use-cases, with ugly names, and 2 of
them having poor failure semantics is not a good direction. Adding
only 2 functions which cover 6 use-cases, with nice names, and good
failure conditions is better. Please reconsider.
>
+1 for this proposal, I would even go one step further and suggest a single
function, with an index as second argument:
`if ([$key, $value] = array_index($input, $index) {`
when `0 === $index` => returns the first, `-1 === $index` returns the last,
etc.
>
> if ([$key, $value] = array_last($input) {
> // do something
> }
>
>
Unfortunately, this won't work. I didn't know list() could even be used as
an expression, but apparently if it is, it evaluates to the whole array on
its right-hand side, which makes sense.
So, if array_last([]) returns [null, null], then [$key,
$value]=array_last([]) will also evaluate to [null, null]. Since that's not
an empty array (it has two elements in it), it will evaluate to true.
https://3v4l.org/lIEa1
If, on the other hand, array_last([]) returned something empty, like [],
the list() assignment would throw Notices for the implicit access to
elements [0] and [1] of the empty array. https://3v4l.org/qhq5R
Regards,
--
Rowan Collins
[IMSoP]
>
>
>>
>>
>> if ([$key, $value] = array_last($input) {
>> // do something
>> }
>>
>
>
> Unfortunately, this won't work. I didn't know list() could even be used as an expression, but apparently if it is, it evaluates to the whole array on its right-hand side, which makes sense.
>
> So, if array_last([]) returns [null, null], then [$key, $value]=array_last([]) will also evaluate to [null, null]. Since that's not an empty array (it has two elements in it), it will evaluate to true. https://3v4l.org/lIEa1
>
> If, on the other hand, array_last([]) returned something empty, like [], the list() assignment would throw Notices for the implicit access to elements [0] and [1] of the empty array. https://3v4l.org/qhq5R
It returns `?array`. So either `null` or `[$key, $value]`. There are
no notices; sorry for the lack of detail.
It returns
?array
. So eithernull
or[$key, $value]
. There are
no notices; sorry for the lack of detail.
See https://3v4l.org/2hX3Y for example
> On Wed, Jun 20, 2018 at 8:09 AM Rowan Collins
> wrote:
> >
> >
> >>
> >>
> >> if ([$key, $value] = array_last($input) {
> >> // do something
> >> }
> >>
> >
> >
> > Unfortunately, this won't work. I didn't know list() could even be used
> as an expression, but apparently if it is, it evaluates to the whole array
> on its right-hand side, which makes sense.
> >
> > So, if array_last([]) returns [null, null], then [$key,
> $value]=array_last([]) will also evaluate to [null, null]. Since that's not
> an empty array (it has two elements in it), it will evaluate to true.
> https://3v4l.org/lIEa1
> >
> > If, on the other hand, array_last([]) returned something empty, like [],
> the list() assignment would throw Notices for the implicit access to
> elements [0] and [1] of the empty array. https://3v4l.org/qhq5R
>
> It returns `?array`. So either `null` or `[$key, $value]`. There are
> no notices; sorry for the lack of detail.
>
Ah, OK, you learn something every day! For anyone else like me who was
unaware of this, list() apparently silently accepts any non-array value on
the right of the assignment, assigns all variables in the list() to null,
and evaluates to the assigned (but otherwise unused) value. So
$x=list($a,$b)=42; will set $a and $b to NULL, and $x to 42, without any
notices.
I don't think I would ever have expected that behaviour, but apparently
it's been that way forever, so I guess it's fine to exploit it.
Incidentally, there's no mention of this on the manual page, which is also
missing information on the short-hand syntax and key-based destructuring
introduced in PHP 7.1: http://php.net/list
Regards,
--
Rowan Collins
[IMSoP]
Ah, OK, you learn something every day! For anyone else like me who was unaware of this, list() apparently silently accepts any non-array value on the right of the assignment, assigns all variables in the list() to null, and evaluates to the assigned (but otherwise unused) value. So $x=list($a,$b)=42; will set $a and $b to NULL, and $x to 42, without any notices.
This is changing as per this RFC:
https://wiki.php.net/rfc/notice-for-non-valid-array-container. The
null
case is kept.
Ah, OK, you learn something every day! For anyone else like me who was
unaware of this, list() apparently silently accepts any non-array value on
the right of the assignment, assigns all variables in the list() to null,
and evaluates to the assigned (but otherwise unused) value. So
$x=list($a,$b)=42; will set $a and $b to NULL, and $x to 42, without any
notices.This is changing as per this RFC:
https://wiki.php.net/rfc/notice-for-non-valid-array-container. The
null
case is kept.
Not according to the RFC:
Per discussion on the PR
https://github.com/php/php-src/pull/2031#issuecomment-238366706 I have
limited this RFC to not raise warnings when setting any value by use of
list().
It says nothing about treating NULL
specially, it just implies list() will
be out of scope of the RFC completely.
Regards,
Rowan Collins
[IMSoP]
Am 20.06.2018 um 15:55 schrieb Levi Morrison:
Your wish cannot be granted for
array_value_last
and
array_value_first
; you cannot know by itself if there is a failure
condition.
I can comprehend your issue with the lack of distinctness between the
error case and the 'real' array value null without further checks.
But in my opinion the required additional checking of the $input is a
learned behaviour from existing functions which handle single value
elements from an array as reset()
, current()
and end()
will return false
for empty arrays or null for invalid data types which are both also
valid element values.
array_pop()
and array_shift()
also behave in a comparable way as they
return null as well for empty arrays as for non array input.
This is not "clean". In contrast here is with my proposal:
if ([$key, $value] = array_last($input) { // do something }
I still think that this proposed syntax is unintuitive and hard to
comprehend for the user of the function.
I don't think many PHP developers out there know that the condition
inside the if will evaluate to null if array_last returns null.
Additionally I don't know about any other function where a construct
like this has to be used to extract two or more different semantic
entities, in this case the key and the value, out of a PHP core function
return value.
Enno
Am 20.06.2018 um 15:55 schrieb Levi Morrison:
Your wish cannot be granted for
array_value_last
and
array_value_first
; you cannot know by itself if there is a failure
condition.I can comprehend your issue with the lack of distinctness between the
error case and the 'real' array value null without further checks.
But in my opinion the required additional checking of the $input is a
learned behaviour from existing functions which handle single value
elements from an array asreset()
,current()
andend()
will return false
for empty arrays or null for invalid data types which are both also
valid element values.
array_pop()
andarray_shift()
also behave in a comparable way as they
return null as well for empty arrays as for non array input.This is not "clean". In contrast here is with my proposal:
if ([$key, $value] = array_last($input) { // do something }
I still think that this proposed syntax is unintuitive and hard to
comprehend for the user of the function.
I don't think many PHP developers out there know that the condition
inside the if will evaluate to null if array_last returns null.Additionally I don't know about any other function where a construct
like this has to be used to extract two or more different semantic
entities, in this case the key and the value, out of a PHP core function
return value.
Bad behavior of existing functions does not mean we should create new
functions with the same bad behavior. If you believe lack of education
regarding array destructuring is an issue then we can use this example
specifically in the docs for these functions; problem solved.
We can do better and I've shown how we can do better. Please adopt it.
Bad behavior of existing functions does not mean we should create new
functions with the same bad behavior. If you believe lack of education
regarding array destructuring is an issue then we can use this example
specifically in the docs for these functions; problem solved.
I'm torn between your point of view and Enno's.
Note that we're not talking about "lack of education regarding array
destructuring", because there's no array being destructured; we're talking
about "lack of education regarding the side-effect behaviour of the array
destructuring operator when given a non-array input". It's a pretty
obscure, seemingly undocumented, language feature, and one which the RFC
you linked seems to have originally classed as unwanted behaviour.
If it was used in a prominent example, maybe other uses for this idiom
might start cropping up, and people would start using it. Even so, if I saw
it while reviewing or debugging code, I would probably be tempted to
refactor it to something "less clever" so that the intent was clearer.
On balance, I don't think the example you gave is a compelling reason, on
its own, to go with your suggested signature. The separate functions feel
more convenient in a lot of cases, but maybe less so in others.
Regards,
Rowan Collins
[IMSoP]
don't think I'm getting all the mail I am supposed to. I hope this gets
seen.I propose 2 functions only which I believe covers the use-cases that
all 4 of these do and more, with shorter names, and the ability to
discern whether the call succeeded or not.list($key, $value) = array_first($input); // $key will be null if the call failed list($key, $value) = array_last($input); // $key will be null if the call failed
I have tested it with user-land functions and seems to work as
intended in all success and failure conditions. Verification that it
works as intended with internal functions is necessary but this seems
a much better proposal to me.--
Hi Levi.
I have plans to bring an array_find_first
and array_find_last
to the
next PHP 7.x. It will basically work:
$firstUserWithUsername = array_find_first(function (User $user): bool {
return $user->username !== null;
}, $users);
Just wanted to point that to alert that someone is working on that :)
Gabriel Caruso
I don't think I'm getting all the mail I am supposed to. I hope this gets
seen.I propose 2 functions only which I believe covers the use-cases that
all 4 of these do and more, with shorter names, and the ability to
discern whether the call succeeded or not.list($key, $value) = array_first($input); // $key will be null if the call failed list($key, $value) = array_last($input); // $key will be null if the call failed
I have tested it with user-land functions and seems to work as
intended in all success and failure conditions. Verification that it
works as intended with internal functions is necessary but this seems
a much better proposal to me.
Can I vote "heck no" to any function that does multi-return, thus making it
impossible to chain or pass directly to another function? That's an idiom
that just doesn't make sense in PHP.
--Larry Garfield
Brainstorm suggestions:
- Keys being stored as reference:
$valueOutput = array_first(array $array, ?string &$keyOutput = null);
- Function will returns value or key, by option (similar to
array_filter()
):
array_first(array $array, int $options = ARRAY_VALUE);
array_first(array $array, int $options = ARRAY_KEY);
3.
F
unction will returns value or key, by boolean argument:
array_first(array $array, bool $returnKeyInsteadOfValue = false);
array_first(array $array, bool $returnKeyInsteadOfValue = true);
- Specific method to return key instead of value:
array_first(array $array);
array_first_key(array $array);
- Consider that keys could be obtained via
array_keys()
, so array_first()
should just care about values:
array_first(array_keys($array));
Em qui, 21 de jun de 2018 às 13:18, Larry Garfield larry@garfieldtech.com
escreveu:
I don't think I'm getting all the mail I am supposed to. I hope this gets
seen.I propose 2 functions only which I believe covers the use-cases that
all 4 of these do and more, with shorter names, and the ability to
discern whether the call succeeded or not.list($key, $value) = array_first($input); // $key will be null if the call failed list($key, $value) = array_last($input); // $key will be null if the call failed
I have tested it with user-land functions and seems to work as
intended in all success and failure conditions. Verification that it
works as intended with internal functions is necessary but this seems
a much better proposal to me.Can I vote "heck no" to any function that does multi-return, thus making
it
impossible to chain or pass directly to another function? That's an idiom
that just doesn't make sense in PHP.--Larry Garfield
--
David Rodrigues
Hi David,
thanks for your brainstorming suggestions. My opinion on the options:
- Keys being stored as reference:
$valueOutput = array_first(array $array, ?string &$keyOutput = null);
In my opinion using references to return additional values from a
function is quiet hacky. I think returning a single value leads to
significantly clearer code and thus supports the developer.
- Function will returns value or key, by option (similar to
array_filter()
):
array_first(array $array, int $options = ARRAY_VALUE);
array_first(array $array, int $options = ARRAY_KEY);
This violates the single responsibility principle and consequently isn't
a good move
3.
F
unction will returns value or key, by boolean argument:array_first(array $array, bool $returnKeyInsteadOfValue = false);
array_first(array $array, bool $returnKeyInsteadOfValue = true);
Compare 2.
- Specific method to return key instead of value:
array_first(array $array);
array_first_key(array $array);
This is the RFC just with slightly different function names. I think
using array_key_first and array_value_first (and the corresponding
functions for the last array element) provides a consistent naming.
- Consider that keys could be obtained via
array_keys()
, so array_first()
should just care about values:array_first(array_keys($array));
This solution requires a copy of the array (keys) which extends the time
complexity and the memory usage of the task.
Regards,
Enno
Hi all,
I just want to add some information that I feel it's missing in that
discussion - I'm sorry if it was mentioned already.
-
It's already possible to extract the key and value of any index
position of an array using array_slice: https://3v4l.org/mib99 -
"array_[key|value]first|last" is in my opinion not a good
option as it lacks the possibility to extract key/value from any position.
Something like "array[key|value]_index($array, $index)" where $index
would be the index position or negative index position from right.
Thanks,
Marc
Am 21.06.2018 um 18:16 schrieb Larry Garfield:
I don't think I'm getting all the mail I am supposed to. I hope this gets
seen.I propose 2 functions only which I believe covers the use-cases that
all 4 of these do and more, with shorter names, and the ability to
discern whether the call succeeded or not.list($key, $value) = array_first($input); // $key will be null if the call failed list($key, $value) = array_last($input); // $key will be null if the call failed
I have tested it with user-land functions and seems to work as
intended in all success and failure conditions. Verification that it
works as intended with internal functions is necessary but this seems
a much better proposal to me.Can I vote "heck no" to any function that does multi-return, thus making it
impossible to chain or pass directly to another function? That's an idiom
that just doesn't make sense in PHP.--Larry Garfield
Hi all,
I just want to add some information that I feel it's missing in that
discussion - I'm sorry if it was mentioned already.
It's already possible to extract the key and value of any index
position of an array using array_slice: https://3v4l.org/mib99"array_[key|value]first|last" is in my opinion not a good
option as it lacks the possibility to extract key/value from any position.
Something like "array[key|value]_index($array, $index)" where $index
would be the index position or negative index position from right.
The big advantage of separate functions is that they make the intent clear;
we could combine all four functions into one: array_index(int $position,
bool $key), but "array_key_last($something)" is a lot clearer to read than
"array_index($something, -1, true)". Are there actually use cases for
getting "the 5th key from the end of the array", common enough to make "the
last key in the array" harder to write?
Regards,
Rowan Collins
[IMSoP]
Am 26.06.2018 um 16:42 schrieb Rowan Collins:
Hi all,
I just want to add some information that I feel it's missing in that
discussion - I'm sorry if it was mentioned already.
It's already possible to extract the key and value of any index
position of an array using array_slice: https://3v4l.org/mib99"array_[key|value]first|last" is in my opinion not a good
option as it lacks the possibility to extract key/value from any position.
Something like "array[key|value]_index($array, $index)" where $index
would be the index position or negative index position from right.The big advantage of separate functions is that they make the intent clear;
we could combine all four functions into one: array_index(int $position,
bool $key), but "array_key_last($something)" is a lot clearer to read than
"array_index($something, -1, true)". Are there actually use cases for
getting "the 5th key from the end of the array", common enough to make "the
last key in the array" harder to write?Regards,
As well as Rowan I don't see use cases for fetching keys/values at any
position inside the array for justifying to break up the current
readable function signatures.
Combining multiple use cases and tasks into a single function always
offends the single responsibility principle (compare my previous mail)
and thus should be avoided.
Are there other opinions concerning this topic?
I'd like to finish the discussion soon and move on to the voting phase.
Regards,
Enno
Are there other opinions concerning this topic?
In my opinion, there are already too many array functions, so I'm not
fond of adding more to it. That said, I see the usefulness of
array_key_first() and array_key_last(), but not of array_value_first()
and array_value_last(), since these could easily be implemented on top
of the key functions in userland. Also, it would be possible to
implement the suggested array_first() and array_last() on top of the key
functions, with whatever signature the user desires.
Anyhow, thanks for the RFC!
--
Christoph M. Becker
Am 26.06.2018 um 16:42 schrieb Rowan Collins:
Hi all,
I just want to add some information that I feel it's missing in that
discussion - I'm sorry if it was mentioned already.
It's already possible to extract the key and value of any index
position of an array using array_slice: https://3v4l.org/mib99"array_[key|value]first|last" is in my opinion not a good
option as it lacks the possibility to extract key/value from any position.
Something like "array[key|value]_index($array, $index)" where $index
would be the index position or negative index position from right.The big advantage of separate functions is that they make the intent clear;
we could combine all four functions into one: array_index(int $position,
bool $key), but "array_key_last($something)" is a lot clearer to read than
"array_index($something, -1, true)". Are there actually use cases for
getting "the 5th key from the end of the array", common enough to make "the
last key in the array" harder to write?Regards,
As well as Rowan I don't see use cases for fetching keys/values at any
position inside the array for justifying to break up the current
readable function signatures.
Combining multiple use cases and tasks into a single function always
offends the single responsibility principle (compare my previous mail)
and thus should be avoided.Are there other opinions concerning this topic?
I'd like to finish the discussion soon and move on to the voting phase.
I think there has been a lack of discussion about why this is desired.
For me, it's always been implementing certain kinds of iterators that
wrap arrays. This means that functions which return both the key and
value are optimal for me. As I already outlined the functions which
return the key-value pair are the most general and do result in clean
code without drawbacks, at least for this use-case.
Some people do not like this idea. One potential implication this that
maybe their use-case is not the same as mine. What use-cases do other
people have for this? Why are you wanting to grab the first or last
value? What data structure or algorithm is this a bigger part of?
Am 28.06.2018 um 16:52 schrieb Levi Morrison:
I think there has been a lack of discussion about why this is desired.
For me, it's always been implementing certain kinds of iterators that
wrap arrays. This means that functions which return both the key and
value are optimal for me. As I already outlined the functions which
return the key-value pair are the most general and do result in clean
code without drawbacks, at least for this use-case.Some people do not like this idea. One potential implication this that
maybe their use-case is not the same as mine. What use-cases do other
people have for this? Why are you wanting to grab the first or last
value? What data structure or algorithm is this a bigger part of?
Hi Levi,
sorry for the long-lasting answer.
I use plain arrays relatively often when I develop caching mechanics for
multiple rather complex entities. I query a set of suitable entites and
store them as a plain array eg. in Redis.
Each request now fetches this preprocessed entities. Sometimes all
entities are required but I also have use cases where I filter/sort the
list of entries and only one entity is interesting (in all cases I
experienced either the first or the last element). This is my initial
use case for this RFC.
Are there other opinions about the necessity of this functions?
Regards,
Enno