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