Welcome! Log In Create A New Profile

Advanced

[PHP-DEV] [RFC][Under Discussion] Add functions array_key_first() and array_key_last()

Posted by Enno Woortmann 
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



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On 13.06.2018 at 21:26, Enno Woortmann wrote:

> 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

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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Hi,

On 13.06.2018 at 23:10, Christoph M. Becker wrote:

> 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>;
>

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



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On 13/06/18 20:26, Enno Woortmann wrote:
> 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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
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


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On 06/15/2018 08:37 AM, niel wrote:
> On 13/06/18 20:26, Enno Woortmann wrote:
>> 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?


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
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.:

[email protected]:/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
[email protected]:/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
[email protected]:/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


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On 17/06/18 23:09, Enno Woortmann wrote:
> 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.:
>
> [email protected]:/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
> [email protected]:/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
> [email protected]:/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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
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


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On 18.06.2018 at 00:09, Enno Woortmann wrote:

> 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.:
>
> [email protected]:/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
> [email protected]:/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
> [email protected]:/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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On Monday, June 18, 2018 4:25:27 AM CDT Christoph M. Becker wrote:
> On 18.06.2018 at 00:09, Enno Woortmann wrote:
> > 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.:
> >
> > [email protected]:/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
> > [email protected]:/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
> > [email protected]:/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.

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
On 18.06.2018 at 17:32, Larry Garfield wrote:

> 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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Hello internals,
On 15.06.2018 at 00:37, Enno Woortmann wrote:
> 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
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.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
>
> 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.
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php


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
On Wed, Jun 20, 2018 at 3:17 AM Woortmann, Enno <[email protected]> wrote:
>
> 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.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
> if ([$key, $value] = array_last($input) {
>

+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.
On 20 June 2018 at 14:55, Levi Morrison <[email protected]> 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

Regards,
--
Rowan Collins
[IMSoP]
On Wed, Jun 20, 2018 at 8:09 AM Rowan Collins <[email protected]> wrote:
>
> On 20 June 2018 at 14:55, Levi Morrison <[email protected]> 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.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
> It returns `?array`. So either `null` or `[$key, $value]`. There are
> no notices; sorry for the lack of detail.
>

See https://3v4l.org/2hX3Y for example
On 20 June 2018 at 15:10, Levi Morrison <[email protected]> wrote:

> On Wed, Jun 20, 2018 at 8:09 AM Rowan Collins <[email protected]>
> wrote:
> >
> > On 20 June 2018 at 14:55, Levi Morrison <[email protected]> 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.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On 20 June 2018 at 15:29, Levi Morrison <[email protected]> wrote:

> > 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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On Wed, Jun 20, 2018 at 10:03 AM Woortmann, Enno <[email protected]> wrote:
>
> 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.

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.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
On 20 June 2018 at 17:19, Levi Morrison <[email protected]> wrote:

> 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]
On Tuesday, June 19, 2018 9:47:01 PM CDT Levi Morrison wrote:
> 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:

1. Keys being stored as reference:

$valueOutput = array_first(array $array, ?string &$keyOutput = null);

2. 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); ​

4. Specific method to return key instead of value:

array_first(array $array);
array_first_key(array $array);

5. 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 <[email protected]>
escreveu:

> On Tuesday, June 19, 2018 9:47:01 PM CDT Levi Morrison wrote:
> > 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 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.

1. It's already possible to extract the key and value of any index
position of an array using array_slice: https://3v4l.org/mib99

2. "array_[key|value]_[first|last]($array)" 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:
> On Tuesday, June 19, 2018 9:47:01 PM CDT Levi Morrison wrote:
>> 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
>

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
Sorry, only registered users may post in this forum.

Click here to login