rfc:additional-splat-usage

This is an old revision of the document!


PHP RFC: Additional Usage Options for the Splat Operator

Introduction

This RFC proposes additional uses for the argument unpacking/variadic argument list operator introduced in PHP 5.6.

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.

Combining arrays in literal declaration syntax

A common operation is to merge an existing array stored in a variable with another array that is being declared literally. Currently this is usually done using array_merge() or the + operator:

$arr1 = ['d' => 4, 'e' => 5, 'f' => 6];
$arr2 = array_merge(['a' => 1, 'b' => 2, 'c' => 3], $arr1);
$arr3 = ['a' => 1, 'b' => 2, 'c' => 3] + $arr1;

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().

This RFC proposes allowing the splat operator to be used in array literals as another way to perform this operation:

$arr1 = ['d' => 4, 'e' => 5, 'f' => 6];
$arr2 = ['a' => 1, 'b' => 2, 'c' => 3, ...$arr1];

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 elements" in list()

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 elements. In order to do this at the moment, something like the following must be done:

$arr = [1, 2, 3, 4, 5, 6];
 
$theRest = array_splice($arr, 2);
list($one, $two) = $arr;

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.

This RFC proposes allowing the splat operator to be used as an argument to the list() construct to simplify this operation:

$arr = [1, 2, 3, 4, 5, 6];
 
list($one, $two, ...$theRest) = $arr;

This behaves in the same manner as a variadic function would, filling $theRest with the any trailing elements of the input array.

Backward Incompatible Changes

None.

Proposed PHP Version(s)

This RFC targets PHP 7.

RFC Impact

To SAPIs

None.

To Existing Extensions

None.

To Opcache

TODO.

Open Issues

None at this time.

Unaffected PHP Functionality

No existing functionality is affected by this, other than the new capabilities outlined in the main proposal.

Proposed Voting Choices

Simple yes/no. As this is a language change, the vote would require a 2/3 majority in favour to pass.

Patches and Tests

Nikita Popov has offered to provide an implementation for this feature should it be accepted.

References

rfc/additional-splat-usage.1414499236.txt.gz · Last modified: 2017/09/22 13:28 (external edit)