问题
I'm playing around with arrays and a flatten
function in order to wrap my head around how Swift uses generics.
However, the following code gives a generic 'Error running playground' popup, and I can't work out why.
Interestingly, if I put the code into a project and try to compile it, the compiler segfaults.
import Cocoa
var arr: [[Int]] = [[1,2], [3,4], [5,6]]
func flatten<S: SequenceType, SS: SequenceType, E where S.Generator.Element == SS, SS.Generator.Element == E>(seq: S) -> [E] {
var result = [E]()
for subseq: SS in seq {
for elem: E in subseq {
result += [elem]
}
}
return result
}
var flattened = flatten(arr)
println(flattened)
Has anyone seen something like this / found a workaround?
Sadly I suspect this might just be a bug with type inference in the beta :(
回答1:
This definitely seems to be some sort of bug with Swift generics (it should at least be showing a compile error instead of apparently crashing).
As for a workaround though, this seems to work:
func flatten<E>(seq: [[E]]) -> [E] {
var result = [E]()
for subseq: [E] in seq {
for elem: E in subseq {
result += [elem]
}
}
return result
}
回答2:
Your flatten
implementation still crashes the compiler, which I still regard as a bug. However, if you define it like this, it works:
func flatten<S: SequenceType, E where S.Generator.Element: SequenceType, S.Generator.Element.Generator.Element == E>(seq: S) -> [E] {
var result = [E]()
for subseq: S.Generator.Element in seq {
for elem: E in subseq {
result += [elem]
}
}
return result
}
This achieves your goal of working with any SequenceType
, not just arrays. (In fact, I wish we could return an even more general type than [E]
. If I were back in C# land, I'd return IEnumerable<E>
, the closest equivalent of SequenceType
, to get even more sexy encapsulation. Swift is a bit leakier.)
来源:https://stackoverflow.com/questions/25194210/what-about-this-code-causes-swift-to-crash