rfc:proper-range-semantics

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
Next revisionBoth sides next revision
rfc:proper-range-semantics [2023/05/08 09:24] – Clarification nits girgiasrfc:proper-range-semantics [2023/06/01 16:16] – In voting girgias
Line 1: Line 1:
 ====== PHP RFC: Define proper semantics for range() function  ====== ====== PHP RFC: Define proper semantics for range() function  ======
  
-  * Version: 0.2+  * Version: 0.3
   * Date: 2023-03-13   * Date: 2023-03-13
   * Author: George Peter Banyard, <girgias@php.net>   * Author: George Peter Banyard, <girgias@php.net>
-  * Status: Under Discussion+  * Status: In Voting
   * Target Version: PHP 8.3   * Target Version: PHP 8.3
   * Implementation: [[https://github.com/php/php-src/pull/10826]]   * Implementation: [[https://github.com/php/php-src/pull/10826]]
Line 19: Line 19:
 The current behaviour is quite complex, and it might be easier to just read the implementation, but it roughly goes as follows: The current behaviour is quite complex, and it might be easier to just read the implementation, but it roughly goes as follows:
  
-First, check if the <php>$step</php> argument is negativeif it is multiply by ''-1''.+First, check if the <php>$step</php> argument is negativeif it is multiply by ''-1''.
  
 Then check the boundary arguments: Then check the boundary arguments:
  
   * If both start and end values are strings with at least one byte (e.g. <php>range('A', 'Z');</php>, <php>range('AA', 'BB');</php>, or <php>range('15', '25');</php>):   * If both start and end values are strings with at least one byte (e.g. <php>range('A', 'Z');</php>, <php>range('AA', 'BB');</php>, or <php>range('15', '25');</php>):
-    * If one of the inputs is a float numeric string, or the <php>$step</php> parameter is a float: go to the handle float input branch +    * If one of the inputs is a float numeric string, or the <php>$step</php> parameter is a float: go to the handle float input branch. 
-    * If one of the inputs is an integer numeric string: go to the generic handling branch+    * If one of the inputs is an integer numeric string: go to the generic handling branch.
     * Otherwise: discard every byte after the first one and return an array of ASCII characters going from the start ASCII code point to the end ASCII code point.     * Otherwise: discard every byte after the first one and return an array of ASCII characters going from the start ASCII code point to the end ASCII code point.
-  * If one of the start or end value is a float or the <php>$step</php> parameter is a float  (e.g. <php>range(10.5, 12);</php>, <php>range(1, 3, 1.5);</php>, or <php>range(1, 3, 1.0);</php>): cast start and end values to float and return an array of floats +  * If the start or end value is a float or the <php>$step</php> parameter is a float  (e.g. <php>range(10.5, 12);</php>, <php>range(1, 3, 1.5);</php>, or <php>range(1, 3, 1.0);</php>): cast start and end values to float and return an array of floats. 
-  * Otherwise (generic handling): cast start and end values to int and return an array of int.+  * Otherwise (generic handling): cast start and end values to int and return an array of integers.
      
 The generic case will accept //any// type. The generic case will accept //any// type.
Line 132: Line 132:
   [4]   [4]
   string(1) "E"   string(1) "E"
 +}
 +
 +
 +var_dump(range('1', '3'));
 +array(3) {
 +  [0]=>
 +  int(1)
 +  [1]=>
 +  int(2)
 +  [2]=>
 +  int(3)
 } }
 </PHP> </PHP>
Line 322: Line 333:
 ==== Issues surrounding usage of INF and NAN values ==== ==== Issues surrounding usage of INF and NAN values ====
  
-Infinite values are handles as part of the range boundary checks, or for the <php>$step</php> parameter when checking that the step is less than the range being requested, and will throw ValueErrors.+Infinite values are handled as part of the range boundary checks, or for the <php>$step</php> parameter when checking that the step is less than the range being requested, and will throw ValueErrors.
  
 However, NAN values are not specifically handled and result in nonsensical ranges: However, NAN values are not specifically handled and result in nonsensical ranges:
Line 339: Line 350:
 </PHP> </PHP>
  
-Where using a NAN values as a step even breaks the expectation that <php>range()</php> will return a non empty list.+Where using a NAN value as a step even breaks the expectation that <php>range()</php> will return a non empty list.
  
 +==== Issues surrounding usage of string digits ====
 +
 +If one of the boundary inputs is a string digit (e.g. ''"1"'') both inputs will be interpreted as numbers.
 +This doesn't pose too much of an issue if both inputs are string digits as it will generate a list of integers.
 +
 +However, if the other input is a non-numeric string the expected behaviour of generating a list of ASCII characters is not upheld anymore:
 +<PHP>
 +var_dump( range("9", "A") );
 +array(10) {
 +  [0]=>
 +  int(9)
 +  [1]=>
 +  int(8)
 +  [2]=>
 +  int(7)
 +  [3]=>
 +  int(6)
 +  [4]=>
 +  int(5)
 +  [5]=>
 +  int(4)
 +  [6]=>
 +  int(3)
 +  [7]=>
 +  int(2)
 +  [8]=>
 +  int(1)
 +  [9]=>
 +  int(0)
 +}
 +</PHP>
 +instead of the expected:
 +<PHP>
 +var_dump( range("9", "A") );
 +array(9) {
 +  [0]=>
 +  string(1) "9"
 +  [1]=>
 +  string(1) ":"
 +  [2]=>
 +  string(1) ";"
 +  [3]=>
 +  string(1) "<"
 +  [4]=>
 +  string(1) "="
 +  [5]=>
 +  string(1) ">"
 +  [6]=>
 +  string(1) "?"
 +  [7]=>
 +  string(1) "@"
 +  [8]=>
 +  string(1) "A"
 +}
 +</PHP>
  
 ===== Proposal ===== ===== Proposal =====
Line 349: Line 415:
  
   * If <php>$step</php> is a float but is compatible with ''int'' (i.e. <php>(float)(int)$step === $step</php>) interpret it as an integer.   * If <php>$step</php> is a float but is compatible with ''int'' (i.e. <php>(float)(int)$step === $step</php>) interpret it as an integer.
-  * Introduce and use a proper ZPP check for ''int|float|string'' <php>$start</php> and <php>$end</php> parametersthis will cause <php>TypeError</php>s to be thrown when passing objects, resources, and arrays to <php>range()</php>. It will also cause a deprecation warning to be emitted when passing ''null''.+  * Introduce and use a proper ZPP check for ''int|float|string'' <php>$start</php> and <php>$end</php> parametersthis will cause <php>TypeError</php>s to be thrown when passing objects, resources, and arrays to <php>range()</php>. It will also cause a deprecation warning to be emitted when passing ''null''.
   * Throw value errors if <php>$start</php>, <php>$end</php>, or <php>$step</php> is a non-finite float (-INF, INF, NAN).   * Throw value errors if <php>$start</php>, <php>$end</php>, or <php>$step</php> is a non-finite float (-INF, INF, NAN).
   * Throw a more descriptive <php>ValueError</php> when <php>$step</php> is zero.   * Throw a more descriptive <php>ValueError</php> when <php>$step</php> is zero.
Line 355: Line 421:
   * Emit an <php>E_WARNING</php> when <php>$start</php> or <php>$end</php> is the empty string, and cast the value to ''0''   * Emit an <php>E_WARNING</php> when <php>$start</php> or <php>$end</php> is the empty string, and cast the value to ''0''
   * Emit an <php>E_WARNING</php> when <php>$start</php> or <php>$end</php> has more than one byte if it is a non-numeric string.   * Emit an <php>E_WARNING</php> when <php>$start</php> or <php>$end</php> has more than one byte if it is a non-numeric string.
-  * Emit an <php>E_WARNING</php> when <php>$start</php> or <php>$end</php> is cast to an integer because the other boundary input is a number or numeric string. (e.g. <php>range('5', 'z');</php> or <php>range(5, 'z');</php>+  * Emit an <php>E_WARNING</php> when <php>$start</php> or <php>$end</php> is cast to an integer because the other boundary input is a number. (e.g. <php>range(5, 'z');</php>
-  * Emit an <php>E_WARNING</php> when <php>$step</php> is a float when trying to generate a range of characters.+  * Produce a list of characters if one of the boundary inputs is a string digit instead of casting the other input to int (e.g. <php>range('5', 'z');</php>
 +  * Emit an <php>E_WARNING</php> when <php>$step</php> is a float when trying to generate a range of characters, except if both boundary inputs are numeric strings (e.g. <php>range('5', '9', 0.5);</php> does not produce a warning).
  
  
Line 375: Line 442:
   [4]=>   [4]=>
   string(1) "E"   string(1) "E"
 +}
 +
 +var_dump( range("9", "A") );
 +array(9) {
 +  [0]=>
 +  string(1) "9"
 +  [1]=>
 +  string(1) ":"
 +  [2]=>
 +  string(1) ";"
 +  [3]=>
 +  string(1) "<"
 +  [4]=>
 +  string(1) "="
 +  [5]=>
 +  string(1) ">"
 +  [6]=>
 +  string(1) "?"
 +  [7]=>
 +  string(1) "@"
 +  [8]=>
 +  string(1) "A"
 } }
  
Line 436: Line 525:
 <php>E_WARNING</php>s are emitted for various issues. <php>E_WARNING</php>s are emitted for various issues.
  
-Calls to <php>range()</php> that have integer boundaries but a float step that is compatible as an integer will now return an array of integers instead of an array of float:+Calls to <php>range()</php> that have integer boundaries but a float step that is compatible as an integer will now return an array of integers instead of an array of floats:
 <PHP> <PHP>
 var_dump( range(1, 5, 2.0) ); var_dump( range(1, 5, 2.0) );
Line 467: Line 556:
 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-06-01 and will end on 2023-06-15
-<doodle title="Accept Saner range() semantics RFC?" auth="girgias" voteType="single" closed="true">+<doodle title="Accept Saner range() semantics RFC?" auth="girgias" voteType="single" closed="false">
    * Yes    * Yes
    * No    * No
rfc/proper-range-semantics.txt · Last modified: 2023/06/19 13:41 by girgias