rfc:spread_operator_for_array

Spread Operator in Array

Introduction

PHP has already supported argument unpacking (AKA spread operator) since 5.6. This RFC proposes to bring this feature to array.

Proposal

An array pair prefixed by … will be expanded in places during array definition. Only arrays and objects who implement Traversable can be expanded.

For example,

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];

It's possible to do the expansion multiple times, and unlike argument unpacking, can be used anywhere. It's possible to add normal elements before or after the spread operator.

Spread operator works for both array syntax(array()) and short syntax([]).

$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr3 = [0, ...$arr1]; //[0, 1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); //[1, 2, 3, 1, 2, 3, 111]

It's possible to unpack arrays with string keys. When unpacking multiple arrays with same string key, the later value for that key will overwrite the previous one.

For arrays with numeric keys, they will be renumbered with incrementing keys starting from zero. So if unpack multiple arrays with same numeric key, the later value will be appended instead of overwriting the previous one.

It's possible to unpack arrays with mixed string and numeric keys.

$arr1 = ['a' => 1, 'b' => 2, 'c'=> 3];
$arr2 = [11 => 11, 22 => 22, 33 => 33];
$arr3 = [111 => 9, 22 => 8, 'c' => 7];
var_dump([...$arr1, ...$arr2]);
/*
array(6) {
  ["a"]=>
  int(1)
  ["b"]=>
  int(2)
  ["c"]=>
  int(3)
  [0]=>
  int(11)
  [1]=>
  int(22)
  [2]=>
  int(33)
}
*/
var_dump([...$arr1, ...$arr3]);
/*
array(5) { 
  ["a"]=>  
  int(1)   
  ["b"]=>  
  int(2)   
  ["c"]=>  
  int(7)   
  [0]=>    
  int(9)   
  [1]=>    
  int(8)   
}          
*/
var_dump([...$arr2, ...$arr3]);
/*
array(6) {
  [0]=>
  int(11)
  [1]=>
  int(22)
  [2]=>
  int(33)
  [3]=>
  int(9)
  [4]=>
  int(8)
  ["c"]=>
  int(7)
}
*/

By-reference passing

It's not possible to unpack an array by reference.

$arr1 = [1, 2, 3];
$arr2 = [...&$arr1]; //invalid

However, if elements in the array to be unpacked are stored by reference, they will be stored by reference in the new array as well.

$one = 1;
$arr1 = [&$one, 2, 3];
$arr2 = [0, ...$arr1];
var_dump($arr2);
/*
array(4) {
  [0]=>
  int(0)
  [1]=>
  &int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
}
*/

Backward Incompatible Changes

This change should not break anything.

Proposed PHP Version(s)

next PHP 7.x, likely 7.4

RFC Impact

To Opcache

I'm not sure if this RFC will have any impact on Opcache. I'll check it after I finish the patch.

Proposed Voting Choices

As this is a language change, a 2/3 majority is required.

Patches and Tests

Implementation

After the project is implemented, this section should contain

  1. the version(s) it was merged into
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature
  4. a link to the language specification section (if any)

References

Links to external references, discussions or RFCs

Rejected Features

Keep this updated with features that were discussed on the mail lists.

rfc/spread_operator_for_array.txt · Last modified: 2018/10/28 03:29 by jhdxr