Summary of the new feature/enhancement
Iterating over multiple collections that have corresponding elements iteratively is a common scenario.
This is currently fairly cumbersome, so letting the foreach statement provide syntactic sugar would be a nice simplification (and would amount to a generalization of the pairwise Linq.Enumerable.Zip() method):
# 3 collections with corresponding elements('foo' relates to 'baz' and 'and', 'bar' relates to 'qux' and 'so on')
$a = 'foo', 'bar'
$b = 'baz', 'qux'
$c = 'and', 'so on'
# WISHFUL THINKING
# Iterate over the corresponding elements from each RHS collection.
# Note: Number of iterator variables must match the number of collections.
foreach ($aElem, $bElem, $cElem in $a, $b, $c) {
"$aElem, $bElem, $cElem"
}
The above would yield:
foo, baz, and
bar, qux, so on
and would be the equivalent of the (far more cumbersome) following:
foreach ($i in 0..($a.count-1)) {
$aElem, $bElem, $cElem = $a[$i], $b[$i], $c[$i]
"$aElem, $bElem, $cElem"
}
Due to its resemblance to destructuring assignments, I think the purpose of the syntax is easy to infer.
Note:
-
With multiple iterator variables on the LHS (which activates the new feature being introduced), their number would be required to match the number of explicitly listed collections (RHS); e.g.:
-
foreach ($aElem, $bElem, $cElem in $a, $b, $c) { ... } ... VALID: 3 iterator variables, 3 collections
-
foreach ($aElem, $bElem in $a, $b, $c) { ... } ... INVALID: only 2 iterator variables vs. 3 collections
-
The single-iterator variable (the currently supported syntax) would continue to function as-is; e.g.:
foreach ($elem in $a, $b, $c) { ... } ... RHS is conceived as a single collection to iterate over directly, resulting in 3 iterations with $elem bound to the values of $a, $b, $c in sequence (irrespective of whether these variables contain scalars or collections).
-
The largest among the RHS collections would drive the number of iterations, and the iterator variables would contain $null for those collections that have run out of elements.
Backward-compatibility considerations: N/A, because the proposed new syntax currently results in a syntax error.
Summary of the new feature/enhancement
Iterating over multiple collections that have corresponding elements iteratively is a common scenario.
This is currently fairly cumbersome, so letting the
foreachstatement provide syntactic sugar would be a nice simplification (and would amount to a generalization of the pairwiseLinq.Enumerable.Zip()method):The above would yield:
and would be the equivalent of the (far more cumbersome) following:
Due to its resemblance to destructuring assignments, I think the purpose of the syntax is easy to infer.
Note:
With multiple iterator variables on the LHS (which activates the new feature being introduced), their number would be required to match the number of explicitly listed collections (RHS); e.g.:
foreach ($aElem, $bElem, $cElem in $a, $b, $c) { ... }... VALID: 3 iterator variables, 3 collectionsforeach ($aElem, $bElem in $a, $b, $c) { ... }... INVALID: only 2 iterator variables vs. 3 collectionsThe single-iterator variable (the currently supported syntax) would continue to function as-is; e.g.:
foreach ($elem in $a, $b, $c) { ... }... RHS is conceived as a single collection to iterate over directly, resulting in 3 iterations with$elembound to the values of$a,$b,$cin sequence (irrespective of whether these variables contain scalars or collections).The largest among the RHS collections would drive the number of iterations, and the iterator variables would contain
$nullfor those collections that have run out of elements.Backward-compatibility considerations: N/A, because the proposed new syntax currently results in a syntax error.