我尝试为枚举添加一个覆盖,以处理可选序列的情况(不会崩溃)。这个想法是,如果序列是有效的 aka .Some,它将枚举该序列,否则枚举一个空序列:
func enumerate2<Seq : SequenceType>(base: Seq?) -> EnumerateSequence<Seq> {
// if optional sequence is specified
if let b = base { return enumerate(b) }
// enumerate empty sequence
let a = Array<Seq.Generator.Element>()
return Swift.enumerate(a)
}
func enumerate3<Seq : SequenceType, T where T == Seq.Generator.Element>(base: Seq?) -> EnumerateSequence<Seq> {
// if optional sequence is specified
if let b = base { return enumerate(b) }
// enumerate empty sequence
let a = Array<T>()
return Swift.enumerate(a)
}
我看到错误:
'Array<Seq.Generator.Element>' does not conform to protocol 'GeneratorType'
在最后的返回行中:return Swift.enumerate(a)
这让我很困惑 EnumerateSequence<Seq>
似乎不符合 GeneratorType
.这似乎是一个足够简单的练习,我可能会遗漏什么?
请注意,上面的代码是为了说明而分开的,后缀 2 和 3 是为了消除歧义。
编辑:
一种变通方法是返回可选序列而不是空序列。
func enumerate<Seq : SequenceType>(base: Seq?) -> EnumerateSequence<Seq>? {
return base != nil ? enumerate(base) : nil
}
然后问题转移到安全地枚举可选值:
public func each<S:SequenceType, T where T == S.Generator.Element>
(seq: S, with fn:(T)->()) {
for s in seq { fn(s) }
}
public func each<S:SequenceType, T where T == S.Generator.Element>
(seq: S?, with fn:(T)->()) {
if let some = seq {
for s in some { fn(s) }
}
}
let es = enumerate(["a", "b", "c", "d"])
each(es) { p in
println("\(p.0), \(p.1)")
}
let b:[Int]? = nil
let nes = enumerate(b)
each(nes) { p in
println("\(p.0), \(p.1)")
}
println("done")
产生:
0, a
1, b
2, c
3, d
done
也许,明确使用 if let... 只是为了更明显,但我仍然对初始编译错误感到好奇。
最佳答案
这不起作用,因为您的函数声明表明您正在返回 EnumerateSequence<Seq>
,但最后一行将返回 EnumerateSequence <Array<Seq.Generator.Element>>
——它们不一样,所以编译器不会允许它。
您需要能够创建 Seq
的空实例类型,但是 SequenceType
协议(protocol)未指定初始化程序 - 您需要沿着链向下查找 ExtensibleCollectionType
要找到带有初始值设定项的协议(protocol),请将您的通用约束更改为该协议(protocol)。然后你可以这样做:
func enumerate3<Seq : ExtensibleCollectionType>(base: Seq?) -> EnumerateSequence<Seq> {
// if optional sequence is specified
if let b = base { return enumerate(b) }
// enumerate empty sequence
let a = Seq()
return enumerate(a)
}
注意:如果您查看 Swift header ,它不会显示 Array
符合 ExtensibleCollectionProtocol
,但它实际上是通过“隐藏” ArrayType
来实现的协议(protocol)。
关于ios - Swift:如何编写采用可选序列类型的枚举变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26812557/