Hello internals,
I would like to start the discussion about the Saner array_(sum|product)()
RFC:
https://wiki.php.net/rfc/saner-array-sum-product
Currently, the array_sum()
and array_product()
behave differently than
their userland implementation as they ignore arrays and objects, and cast
the remaining types to int/float.
This is in contrast with the behaviour of arithmetic operators that throw
TypeErrors on types and values that are not interpretable as int/float.
This RFC aims to resolve this discrepancy.
Best regards,
George P. Banyard
I would like to start the discussion about the Saner
array_(sum|product)() RFC:
https://wiki.php.net/rfc/saner-array-sum-productCurrently, the
array_sum()
andarray_product()
behave differently than
their userland implementation as they ignore arrays and objects, and
cast the remaining types to int/float. This is in contrast with the
behaviour of arithmetic operators that throw TypeErrors on types and
values that are not interpretable as int/float.This RFC aims to resolve this discrepancy.
I think I agree with the premise of this RFC, but I do think a few
details are wrongly addressed.
First of all, a clarification why this produces int(4) would be useful:
$input = [true, STDERR, new stdClass(), [], gmp_init(6)];
$output = array_sum($input);
I had to look up that STDERR
would cast to int(3) :-)
I don't understand why this would result in a warning and a return of
int(50):
$a = [10, 15.6, gmp_init(25)];
var_dump(array_sum($a));
Why doesn't this return float(50.6) instead? I realise that the
array_reduce variant (below) does the same, but it's not what I would
expect:
<?php
$input = [10, 15.6, gmp_init(25)];
$output = array_reduce($input, fn($carry, $value) => $carry + $value, 0);
I think the phrase "If traversing the array transforms the return value
into an object, if that object is not numerically castable an E_WARNING
is emitted and the initial return value is returned instead, which may
change the return value if scalar values were present in the array. "
should come with an example :-)
cheers,
Derick
I would like to start the discussion about the Saner
array_(sum|product)() RFC:
https://wiki.php.net/rfc/saner-array-sum-productCurrently, the
array_sum()
andarray_product()
behave differently than
their userland implementation as they ignore arrays and objects, and
cast the remaining types to int/float. This is in contrast with the
behaviour of arithmetic operators that throw TypeErrors on types and
values that are not interpretable as int/float.This RFC aims to resolve this discrepancy.
I think I agree with the premise of this RFC, but I do think a few
details are wrongly addressed.First of all, a clarification why this produces int(4) would be useful:
$input = [true, STDERR, new stdClass(), [], gmp_init(6)]; $output = array_sum($input);
I had to look up that
STDERR
would cast to int(3) :-)
ACK will clarify this.
I don't understand why this would result in a warning and a return of
int(50):$a = [10, 15.6, gmp_init(25)]; var_dump(array_sum($a));
Why doesn't this return float(50.6) instead? I realise that the
array_reduce variant (below) does the same, but it's not what I would
expect:<?php $input = [10, 15.6, gmp_init(25)]; $output = array_reduce($input, fn($carry, $value) => $carry +
$value, 0);
The issue is that now when encountering an object, if it defines a
do_operation handler, it will use that and not cast the value to a numeric
type.
I suppose it's possible to first check if the entry is an object and do a
manual cast, which might also negate the next issue you mentioned.
I think the phrase "If traversing the array transforms the return value
into an object, if that object is not numerically castable anE_WARNING
is emitted and the initial return value is returned instead, which may
change the return value if scalar values were present in the array. "
should come with an example :-)
Within php-src we don't really have any "practical" examples, FFI\CData can
possibly satisfy this condition by doing something like:
$x = FFI::new("int[2]");
$x[0] = 10;
$x[1] = 25;
var_dump($x + 1);
/* dumps:
object(FFI\CData:int32_t*)#2 (1) {
[0]=>
int(25)
}
*/
I constructed a special class and added it to zend_test to be able to test
this behaviour, but will see if I can wrangle FFI to also show this case.
Best regards,
George P. Banyard
Hello internals,
I've slightly updated the RFC:
https://wiki.php.net/rfc/saner-array-sum-product
I've added an FFI example which overloads addition but cannot be cast to a
numeric type.
And changed the behaviours around objects. An object needs to implement a
numeric cast for it to be added/multiplied, this solves the issue around
having the return value being cast to an object as this cannot happen
anymore.
Best regards,
George P. Banyard
Hello internals,
If there are no further feedback I intend on opening the vote for this
tomorrow.
Best regards,
George P. Banyard
Hello,
the RFC seems like a good idea to me.
However, I do not see any mention of plus operator on arrays, e.g. ['a' =>
'A'] + ['b' => 'B']. The array_reduce()
would support this, but I think
array_sum()
would not, because of the return type. I just think this should
be made more explicit.
-- Andreas
Hello internals,
If there are no further feedback I intend on opening the vote for this
tomorrow.Best regards,
George P. Banyard
Hello,
the RFC seems like a good idea to me.
However, I do not see any mention of plus operator on arrays, e.g. ['a' =>
'A'] + ['b' => 'B']. Thearray_reduce()
would support this, but I think
array_sum()
would not, because of the return type. I just think this should
be made more explicit.
-- Andreas
Arrays are mentioned in the RFC, and they are already not supported in the
array_(sum|product) functions and remain unsupported.
Best,
George P. Banyard