[Mutator]: Spread operator in Array Expression - leave only the first element#784
[Mutator]: Spread operator in Array Expression - leave only the first element#784maks-rafalko merged 11 commits intomasterfrom
Conversation
|
Great idea! I'm all in for the variant with an |
|
@sanmai no problem, implemented. The new mutations are: - $a = [...[1, 2, 3], 4];
+ $a = [[1, 2, 3][0], 4];
- $a = [...$collection, 4];
+ $a = [is_array($collection) ? $collection[0] : iterator_to_array($collection)[0], 4];
- $a = [...getCollection(), 4];
+ $a = [is_array(getCollection()) ? getCollection()[0] : iterator_to_array(getCollection())[0], 4]; |
``` Parse error: syntax error, unexpected '...' (T_ELLIPSIS), expecting ']' ```
This reverts commit 38584b7.
``` Parse error: syntax error, unexpected '...' (T_ELLIPSIS), expecting ']' ```
|
I wish It may be better to use $array = [1 => 'bar','baz'];
$example = [...$array, 'foo']; |
|
makes sense, updated the code |
|
Unfortunately, Notice: Only variables should be passed by referenceI see only one solution - introduce a variable: - $arr = [...arrGen()];
+ $_traversable = arrGen();
+ $arr = [is_array($_traversable) ? reset($_traversable) : reset(iterator_to_array($_traversable)));UPD: we can also use function getArray() {
return [1 => 11, 2 => 22];
}
array_slice(getArray(), 0, 1)[0]; // 11and the diff - $arr = [...arrGen()];
+ $arr = [array_slice(is_array($_traversable) ? $_traversable : iterator_to_array($_traversable), 0, 1)[0]]; |
8c14e09 to
778b133
Compare
|
Updated to use If the array has string keys, it's not a problem, because spread operator can not work with string keys. |
778b133 to
3a58388
Compare
|
Yes, otherwise put you can't use a spread operator with such an array in the first place. Do you think this can work? |
Not sure I got the question. If this is the original code before mutation, then the current state of PR works nice with it: $collection = [5, 6, 7];
- $a = [[...$collection][0], 4];
+ $a = [[array_slice(is_array($collection) ? $collection : iterator_to_array($collection), 0, 1][0], 4];which results to [[5][0], 4]
// and then
[5, 4] |
|
I'm more about this mutation: - $a = [...$collection, 4];
+ $a = [[...$collection][0], 4];
- $a = [...getCollection(), 4];
+ $a = [[...getCollection()][0], 4];If it works, we should be able to cut on |
|
👏 awesome Updated the code and added more tests for |
|
Thank you @sanmai for review and ideas |
RFC: https://wiki.php.net/rfc/spread_operator_for_array
PHP 7.4+
This mutator does the following mutations:
The only one issue I think will be with this mutator, is that it can work with any
\Traversable, including\Generator, and the following mutation will be self-killed:function arrGen() { for($i = 11; $i < 15; $i++) { yield $i; } } - $arr = [...arrGen()]; + $arr = [arrGen()[0]];Produces an error:
What can we do?
The first and the best solution is to exactly know what is the return type hint of
arrGen()function and knowing that, do eitherarrGen()[0]for array oriterator_to_array(arrGen())[0]for iterator. However, unfortunately, Infection is not able to guess types at the moment (as for example PHPStan/Psalm do it)The second option is to always do such mutation
Thoughts?