+1 This is needed functionality, and this seems to me to be the natural spelling for pack iteration in Swift.
Also excited for the mentioned future extension to guard let
.
+1 This is needed functionality, and this seems to me to be the natural spelling for pack iteration in Swift.
Also excited for the mentioned future extension to guard let
.
I think this is a pretty good solution, and sorry if this is so much of a Future Direction as to be off-topic, but is there space in this syntax to allow iterating over a pack and a collection at the same time? In particular, I can easily imagine it would be nice to have some equivalent of enumerated
:
for (i, next) in repeat (each 0..., each element) {
print(i, next)
}
I donāt think this exact syntax works because the compiler canāt prove 0...
is at least as long as each element
. Maybe itāll have to use some function like
// UNTESTED
// A bit clunky, used to construct a pack
// with the same length as another pack
// but a different element type.
// No idea if it works.
typealias Second<FirstType, SecondType> = SecondType
func take<each PackElement, Items: Sequence>(
from items: Items,
matching packElement: repeat each PackElement
) -> (repeat Second<each PackElement, Items.Element>) {
var iter = items.makeIterator()
return (repeat (each packElement, iter.next()!).1)
}
for (i, next) in repeat (
take(from: 0..., matching: each element),
each element
) {
print(i, next)
}
Now that I write that out I think that makes sense. Itās a bit verbose, but it makes the collection-to-pack conversion explicit.
The untested code actually already works under this proposal! But because you're making a new iterator every time take
is called, i
will always be 0
. Here's the modified version that will produce the desired behavior (it also already works):
func enumerated<each T>(_ t: repeat each T) -> (repeat (Int, each T)) {
func advance(_ i: inout Int) -> Int {
defer { i = i + 1 }
return i
}
var index = 0
return (repeat (advance(&index), each t))
}
func variadic<each Element>(element: repeat each Element) {
let enumerated = enumerated(repeat each element)
for (i, el) in repeat each enumerated {
print("\(i): \(el)")
// 0: first
// 1: 3
// 2: true
}
}
variadic(element: "first", 3, true)
Also this example helped to uncover a bug in the current implementation: getting rid of enumerated
variable and replacing it with the call to the enumerated
function will crash the compilerš
Will be working on fixing that.
And to do that with an arbitrary collection, youād use an Iterator instead of Int! Thanks, Sima.