====== Spread Operator in Array Expression ====== * Version: 0.2 * Date: 2018-10-13 * Author: CHU Zhaowei, jhdxr@php.net * Status: Implemented (in PHP 7.4) * First Published at: http://wiki.php.net/rfc/spread_operator_for_array ===== Introduction ===== PHP has already supported [[rfc:argument_unpacking|argument unpacking]] (AKA spread operator) since 5.6. This RFC proposes to bring this feature to array expression. ===== 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(''[]''). It's also possible to unpack array returned by a function immediately. $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] $arr5 = [...$arr1, ...$arr1]; //[1, 2, 3, 1, 2, 3] function getArr() { return ['a', 'b']; } $arr6 = [...getArr(), 'c']; //['a', 'b', 'c'] $arr7 = [...new ArrayIterator(['a', 'b', 'c'])]; //['a', 'b', 'c'] function arrGen() { for($i = 11; $i < 15; $i++) { yield $i; } } $arr8 = [...arrGen()]; //[11, 12, 13, 14] ==== String keys ==== In order to make the behavior consistent with [[rfc:argument_unpacking|argument unpacking]], string keys are not supported. A recoverable error will be thrown once a string key is encountered. ==== By-reference passing ==== It's not possible to unpack an array by reference. $arr1 = [1, 2, 3]; $arr2 = [...&$arr1]; //invalid syntax 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. ===== Q & A ===== ==== Advantages over array_merge ==== - Spread operator should have a better performance than ''array_merge''. It's because not only that spread operator is a language structure while ''array_merge'' is a function call, but also compile time optimization can be performant for constant arrays. - ''array_merge'' only supports array, while spread operator also supports objects implementing ''Traversable''. // Before array_merge(iterator_to_array($iter1), iterator_to_array($iter2)) // Or to generalize to all iterables array_merge( is_array($iter1) ? $iter1 : iterator_to_array($iter1), is_array($iter2) ? $iter2 : iterator_to_array($iter2) ) // After (handles both cases) [ ...$iter1, ...$iter2 ] //Thanks Rowan for providing this example ==== ... should be preserved for other use (e.g. map concat) ==== This is kind of out of scope here to discuss other concat / merge operation. The important thing is we should make the behavior of same operator consistent and not to confuse userland developer. It's also why I changed the behavior for string keys in this revised version. ===== Proposed PHP Version(s) ===== next PHP 7.x, likely 7.4 ===== RFC Impact ===== ==== To Opcache ==== Some changes in opcache to support the new opcode is needed. ===== Vote ===== Voting started 2019-04-22 and ends 2019-05-06. A 2/3 majority is required. * Yes * No ===== Patches and Tests ===== WIP https://github.com/php/php-src/pull/3640 ===== Implementation ===== After the project is implemented, this section should contain - the version(s) it was merged into - a link to the git commit(s) - a link to the PHP manual entry for the feature - 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.