rfc:additional-splat-usage

Differences

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

Link to this comparison view

Next revision
Previous revision
rfc:additional-splat-usage [2014/10/28 12:27] – First draft daverandomrfc:additional-splat-usage [2021/06/09 16:03] (current) – Status set to inactive for consistency, it was already part of the "Inactive" list patrickallaert
Line 1: Line 1:
-====== PHP RFC: Additional Usage Options for the Splat Operator ====== +====== PHP RFC: Additional Usage for the Splat Operator ====== 
-  * Version: 0.1 +  * Version: 1.1 
-  * Date: 2014-10-28 +  * Date: 2014-11-03 
-  * Author: Chris Wright, daverandom@php.net +  * Author: Chris Wright, daverandom@php.net, Marcelo Camargo, João Lucchetta 
-  * Status: Draft+  * Status: Inactive
   * First Published at: http://wiki.php.net/rfc/additional-splat-usage   * First Published at: http://wiki.php.net/rfc/additional-splat-usage
  
 ===== Introduction ===== ===== Introduction =====
-This RFC proposes additional uses for the argument unpacking/variadic argument list operator introduced in PHP 5.6.+This RFC proposes an additional usage in array literal declarations for the argument unpacking operator introduced in PHP 5.6.
  
 ===== Proposal ===== ===== Proposal =====
-The argument unpacking operator ''...$var'' (hereafter referred to as the "splat" operator) currently permits unpacking arrays into an argument list when variadic functions are called, as well as collecting variadic arguments into an array in the callee. However, there are other cases where it can make sense to use a similar construct for brevity and readability. There are two key use cases covered by this RFC, both of which are commonly available in other languages that support a similar operator.+The argument unpacking operator ''...$var'' (hereafter referred to as the "splat" operator) currently permits unpacking arrays into an argument list when variadic functions are called, as well as collecting variadic arguments into an array in the callee. However, there are other cases where it can make sense to use a similar construct for brevity and readability. This RFC covers one of these cases which is commonly available in other languages that support a similar operator. This feature is already supported by ECMAScript 6.
  
 ==== Combining arrays in literal declaration syntax ==== ==== Combining arrays in literal declaration syntax ====
Line 22: Line 22:
 </code> </code>
  
-''array_merge()'' is quite verbose and carries the overheads of invoking a function. The ''+'' operator is not always suitable for such an operation and has a cognitive overhead when reading the code, because of the differences in behaviour from ''array_merge()''.+''array_merge()'' is quite verbose and carries the overheads of invoking a function. The ''+'' operator is not always suitable for such an operation and has a cognitive overhead when reading the code, because of the differences in behaviour from ''array_merge()'' and may be confusing because you don't always know if you are dealing with arrays or numbers.
  
 This RFC proposes allowing the splat operator to be used in array literals as another way to perform this operation: This RFC proposes allowing the splat operator to be used in array literals as another way to perform this operation:
Line 33: Line 33:
 The new syntax gives equivalent behaviour to the ''array_merge()'' example above, where the contents of ''$arr1'' are appended to the array literal, and stored in ''$arr2''. The same rules for merging are followed; in the case of duplicated string keys, the later value overwrites the earlier when read from left to right, and numerically indexed arrays are appropriately re-keyed and appended. Any number of variables can be unpacked at any position in the array literal, and may be combined with regular element declarations in any order. The new syntax gives equivalent behaviour to the ''array_merge()'' example above, where the contents of ''$arr1'' are appended to the array literal, and stored in ''$arr2''. The same rules for merging are followed; in the case of duplicated string keys, the later value overwrites the earlier when read from left to right, and numerically indexed arrays are appropriately re-keyed and appended. Any number of variables can be unpacked at any position in the array literal, and may be combined with regular element declarations in any order.
  
-==== "Store the remaining elementsin list() ====+As such, the following application of ''array_merge()'' and of the splat operator and  should be equivalent: 
 +<code php> 
 +$array1 ["color" => "red", "model" => "Corolla"]; 
 +$array2 ["type" => "car", "year" => "2002"];
  
-When unpacking arrays into separate elements via ''list()''it can sometimes be desirable to extract a known set of values from the beginning of an array with an unknown number of elementsIn order to do this at the momentsomething like the following must be done:+$result = array_merge($array1$array2); 
 +$result2 = [...$array1...$array2]; 
 +</code>
  
 +A mixture of applying the splat operator to previously assigned variables and other literal should work just as fine:
 <code php> <code php>
-$arr = [123, 4, 5, 6];+$array1 = ["color" => "red""model" => "Corolla"]; 
 +$array2 = ["type" => "car""year" => "2002"];
  
-$theRest array_splice($arr2); +$result array_merge($array1["category" => "suv", "condition" => "good"], $array2); 
-list($one, $two) = $arr;+$result2 = [...$array1, ...["category" => "suv", "condition" => "good"], ...$array2];
 </code> </code>
  
-The example above is currently the shortest way to perform this operation, and it is not the most readable option - the fact that ''array_splice()'' modifies ''$arr'' may not be immediately obvious if it's not a function that the reader uses a lot, and it's similarity in name to ''array_slice()'', which does almost the same thing but not quite, compounds this cognitive overhead. There are obviously other, more verbose ways to do this that may be considered more readable and obvious, but these involve at least three lines of code for a relatively simple operation.+The operator should have the same behaviour for numeric and associative arrays.  
 +Multidimensional arrays should not be flattened: the splat operator should have effect in the first level keys only.
  
-This RFC proposes allowing the splat operator to be used as an argument to the ''list()'' construct to simplify this operation:+=== Numeric ===
  
 <code php> <code php>
-$arr = [1, 2, 3, 4, 5, 6];+$threetofive = [3,4,5]; 
 +$zerotofive = [0, 1, 2...$threetofive]; 
 +</code>
  
-list($one, $two, ...$theRest) = $arr;+=== Associative === 
 + 
 +<code php> 
 +$addressData = ["street" => "George St.""number" => 2]; 
 +$cityData = ["city" => "Brisbane", "postcode" => 4000]; 
 + 
 +$propertyData = ["name" => "QUT", ...$addressData, ...$cityData];
 </code> </code>
  
-This behaves in the same manner as a variadic function wouldfilling ''$theRest'' with the any trailing elements of the input array.+=== Multidimensional === 
 + 
 +<code php> 
 +$old_marks = [ 
 + "john" => [ 
 +    "maths" => 0, 
 +    "english" => 8 
 + ], 
 + "jane" => [ 
 +    "maths" => 10, 
 +    "english" => 7 
 + ], 
 + "joe" => [ 
 +    "maths" => 0, 
 +    "english" => 8 
 +  ] 
 +]; 
 + 
 +$new_marks = [ 
 +  "matthew" => [ 
 +    "maths" => 5, 
 +    "english" => 5 
 +  ], 
 +  ...$old_marks 
 +]; /* array(4) { ["matthew"]=> ... ["john"]=> ... ["jane"]=> ... ["joe"]=> ... }*/ 
 +</code> 
 + 
 + 
 +Using the splat operator with elements that are not arrays and not ''Traversable'' should cause an error.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 60: Line 104:
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
-This RFC targets PHP 7.+This RFC targets PHP 7.2.
  
 ===== RFC Impact ===== ===== RFC Impact =====
Line 73: Line 117:
  
 ===== Open Issues ===== ===== Open Issues =====
-None at this time.+  * What impact, if any, will this have on Opcache?
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
 No existing functionality is affected by this, other than the new capabilities outlined in the main proposal. No existing functionality is affected by this, other than the new capabilities outlined in the main proposal.
 +
 +===== Future Scope =====
 +
 +Another feature common in languages that implement a similar construct is the ability to store "the rest" of the elements in a ''list()'' assignment operation, in such a manner that the following operations would be equivalent:
 +
 +<code php>
 +$arr = [1, 2, 3, 4, 5, 6];
 +
 +// how we can currently do this
 +$theRest = array_splice($arr, 2);
 +list($one, $two) = $arr;
 +
 +// something that could be implemented instead
 +list($one, $two, ...$theRest) = $arr;
 +</code>
 +
 +This case is not covered by this RFC, because the nature of PHP arrays combined with the way the ''list'' operator works makes this ambiguous with respect to how it should function in the case of arrays which are not simply contiguously 0-indexed. A future RFC could look to implement this, if an agreement could be reached on how it should function.
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
-Simple yes/no. As this is a language change, the vote would require a 2/3 majority in favour to pass.+Extend the splat operator usage yes/no? Requires a 2/3 + 1 majority.
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
-Nikita Popov has offered to provide an implementation for this feature should it be accepted.+Marcelo Camargo is currently writing a patch for this RFC.
  
 ===== References ===== ===== References =====
Line 88: Line 149:
   * [[https://wiki.php.net/rfc/argument_unpacking|Argument unpacking RFC]]   * [[https://wiki.php.net/rfc/argument_unpacking|Argument unpacking RFC]]
   * [[https://wiki.php.net/rfc/variadics|Variadics RFC]]   * [[https://wiki.php.net/rfc/variadics|Variadics RFC]]
 +  * [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator]]
rfc/additional-splat-usage.1414499236.txt.gz · Last modified: 2017/09/22 13:28 (external edit)