rfc:saner-array-sum-product

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:saner-array-sum-product [2023/01/17 02:22] – Add examples girgiasrfc:saner-array-sum-product [2023/03/07 15:43] (current) girgias
Line 1: Line 1:
 ====== PHP RFC: Saner array_(sum|product)()  ====== ====== PHP RFC: Saner array_(sum|product)()  ======
  
-  * Version: 0.1+  * Version: 0.2
   * Date: 2023-01-14   * Date: 2023-01-14
   * Author: George Peter Banyard, <girgias@php.net>   * Author: George Peter Banyard, <girgias@php.net>
-  * Status: Under Discussion+  * Status: [[https://github.com/php/php-src/commit/3b06618813fe0979850eaa1f4bed426edb5b3123|Implemented]]
   * Target Version: PHP 8.3   * Target Version: PHP 8.3
   * Implementation: [[https://github.com/php/php-src/pull/10161]]   * Implementation: [[https://github.com/php/php-src/pull/10161]]
Line 31: Line 31:
 ==== Behaviour of the array_reduce() variants === ==== Behaviour of the array_reduce() variants ===
  
-As the <php>array_reduce()</php> variants use arithmetic operators. It's crucial to understand how they perform with non numeric values. Arithmetic operators perform a numeric type juggling, which is described in the userland manual as:+As the <php>array_reduce()</php> variants use arithmetic operators. It's crucial to understand how they perform with non-numeric values. Arithmetic operators perform a numeric type juggling, which is described in the userland manual as:
  
 <blockquote> <blockquote>
Line 76: Line 76:
 Pathological example: Pathological example:
 <PHP> <PHP>
 +/* STDERR gets cast to 3 */
 $input = [true, STDERR, new stdClass(), [], gmp_init(6)]; $input = [true, STDERR, new stdClass(), [], gmp_init(6)];
  
Line 85: Line 86:
 $output = array_reduce($input, fn($carry, $value) => $carry * $value, 1); $output = array_reduce($input, fn($carry, $value) => $carry * $value, 1);
 var_dump($output); // TypeError var_dump($output); // TypeError
 +</PHP>
 +
 +Certain FFI\CData types implements a ''do_operation'' handler for addition:
 +<PHP>
 +$x = FFI::new("int[2]");
 +$x[0] = 10;
 +$x[1] = 25;
 +
 +$input = [$x, 1];
 +
 +$output = array_reduce($input, fn($carry, $value) => $carry + $value, 0);
 +var_dump($output);
 +/*
 +object(FFI\CData:int32_t*)#4 (1) {
 +  [0]=>
 +  int(25)
 +}
 +*/
 </PHP> </PHP>
  
Line 114: Line 133:
 Pathological example: Pathological example:
 <PHP> <PHP>
 +/* STDERR gets cast to 3 */
 $input = [true, STDERR, new stdClass(), [], gmp_init(6)]; $input = [true, STDERR, new stdClass(), [], gmp_init(6)];
  
Line 121: Line 141:
 $output = array_product($input); $output = array_product($input);
 var_dump($output); // int(3) var_dump($output); // int(3)
 +</PHP>
 +
 +
 +FFI example:
 +<PHP>
 +$x = FFI::new("int[2]");
 +$x[0] = 10;
 +$x[1] = 25;
 +
 +$input = [$x, 1];
 +
 +$output = array_sum($input);
 +var_dump($output); // int(1)
 </PHP> </PHP>
  
Line 127: Line 160:
 The proposal is to use the same behaviour for <php>array_sum()</php> and <php>array_product()</php> as the <php>array_reduce()</php> variants by reusing the engine functions that perform the arithmetic operations while still accepting, but emitting an <php>E_WARNING</php>, and implementing the current behaviours for values that are rejected by the arithmetic operators. The proposal is to use the same behaviour for <php>array_sum()</php> and <php>array_product()</php> as the <php>array_reduce()</php> variants by reusing the engine functions that perform the arithmetic operations while still accepting, but emitting an <php>E_WARNING</php>, and implementing the current behaviours for values that are rejected by the arithmetic operators.
  
-The one caveat is that if the return value would be an object (as is the case when folding over an array of <php>GMP</php> objects) then it must be numerically castable to respect the current return type of ''int|float''. If not, the initial value is returned (''0'' for <php>array_sum()</php> and ''1'' for <php>array_product()</php>).+The one caveat is that objects must implement a numeric cast for them to be added/multiplied, this is done to respect the current return type of ''int|float''.
  
-Therefore the previous two examples would result in the following behaviour:+Thereforethe previous three examples would result in the following behaviour:
  
 Example with <php>GMP</php> objects: Example with <php>GMP</php> objects:
Line 168: Line 201:
 Warning: array_product(): Multiplication is not supported on type array in %s on line %d Warning: array_product(): Multiplication is not supported on type array in %s on line %d
 int(18) int(18)
 +*/
 +
 +</PHP>
 +FFI example:
 +<PHP>
 +$x = FFI::new("int[2]");
 +$x[0] = 10;
 +$x[1] = 25;
 +
 +$input = [$x, 1];
 +
 +$output = array_sum($input);
 +var_dump($output); // int(1)
 +/*
 +
 +Warning: array_sum(): Addition is not supported on type FFI\CData in %s on line %d
 +int(1)
 */ */
 </PHP> </PHP>
Line 176: Line 226:
 <php>E_WARNING</php>s are emitted for incompatible types. <php>E_WARNING</php>s are emitted for incompatible types.
  
-If traversing the array transforms the return value into an object, if that object is not numerically castable an <php>E_WARNING</php> is emitted and the initial return value is returned instead, which may change the return value if scalar values were present in the array. +Arrays that contain objects may now produce different results, for example:
- +
-Arrays that mix scalar values and objects may now produce different results, for example:+
 <PHP> <PHP>
 $a = [10, 15.6, gmp_init(25)]; $a = [10, 15.6, gmp_init(25)];
Line 185: Line 233:
 Currently, results in: ''float(25.6)'' but with this proposal accepted would result in: Currently, results in: ''float(25.6)'' but with this proposal accepted would result in:
 <PHP> <PHP>
-Deprecated: Implicit conversion from float 25.6 to int loses precision in %s on line %d +int(50.6)
-int(50)+
 </PHP> </PHP>
  
Line 198: Line 245:
 As per the voting RFC a yes/no vote with a 2/3 majority is needed for this proposal to be accepted. As per the voting RFC a yes/no vote with a 2/3 majority is needed for this proposal to be accepted.
  
-Voting started on 2023-XX-XX and will end on 2023-XX-XX.+Voting started on 2023-02-20 and will end on 2023-03-06.
 <doodle title="Accept Saner array_(sum|product)() RFC?" auth="girgias" voteType="single" closed="true"> <doodle title="Accept Saner array_(sum|product)() RFC?" auth="girgias" voteType="single" closed="true">
    * Yes    * Yes
Line 207: Line 254:
  
 GitHub pull request: https://github.com/php/php-src/pull/10161 GitHub pull request: https://github.com/php/php-src/pull/10161
 +
 +Landed in PHP 8.3:
 +Implemented via commit: https://github.com/php/php-src/commit/3b06618813fe0979850eaa1f4bed426edb5b3123
  
 After the project is implemented, this section should contain After the project is implemented, this section should contain
rfc/saner-array-sum-product.1673922122.txt.gz · Last modified: 2023/01/17 02:22 by girgias