ios - Swift:如何编写采用可选序列类型的枚举变体

标签 ios xcode macos swift

我尝试为枚举添加一个覆盖,以处理可选序列的情况(不会崩溃)。这个想法是,如果序列是有效的 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/

相关文章:

ios - 尝试在 iOS 中查找反向相同的最长子字符串时出现内存错误

java - 如何在 Sparkle updater(java app) 中等待用户操作?

ios - 大标题到常规标题及其背面

ios - 对静态库的非托管 C# 调用

ios - 锁定的 iOS 设备扫描 BLE 设备

iphone - Object with NSmutableArray of objects with nsmutablearray of objects-如何释放

ios - 从 CoreData 读取数组时共享扩展崩溃

macos - NSMenuItem 操作未执行

macos - 在 Swift 中以编程方式为 OS X 构建 UI(没有 Interface Builder)

ios - iCarousel viewForItemAtIndex 使用自定义 UIView 重新使用第一个加载的图像