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 15:02] – Wording clarification 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:+Therefore, the 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 175: Line 225:
  
 <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 contain objects may now produce different results, for example:
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.1673967759.txt.gz · Last modified: 2023/01/17 15:02 by girgias