swift - 结合使用 AnySequence 和 anyGenerator

标签 swift generics

另一个问题本质上是问如何实现一个 take 函数,它会返回一个序列的前 n 个元素。我的回答是:

struct TakeFromSequenceSequence<S:SequenceType> : SequenceType {
    var limit : Int
    var sequence : S

    func generate() -> AnyGenerator<S.Generator.Element> {
        var generator = sequence.generate()
        var limit = self.limit

        return anyGenerator {
            guard limit > 0 else {
                return nil
            }

            limit = limit - 1

            return generator.next()
        }
    }
}

extension SequenceType {
    func take(count:Int) -> TakeFromSequenceSequence<Self> {
        return TakeFromSequenceSequence(limit: count, sequence: self)
    }
}

但似乎我应该能够使用 AnySequenceanyGenerator 在我的 take 函数中内联完成这一切:

extension SequenceType {
    func take(count:Int) -> AnySequence<Self.Generator.Element> {
        // cannot invoke initializer for type 'AnySequence<_>' with an argument list of type '(() -> _)'
        return AnySequence({
            var generator = self.generate()
            var limit = count

            // cannot invoke 'anyGenerator' with an argument list of type '(() -> _)'
            return anyGenerator({
                guard limit > 0 else {
                    return nil
                }

                limit = limit - 1

                return generator.next()
            })
        })
    }
}

不幸的是,这会产生多个输入错误,主要是(我认为)因为类型推断失败。

有人对如何让这个(使用 AnySequenceanyGenerator 内联)工作有任何建议吗?

最佳答案

(现在的答案是基于Swift 2.2/Xcode 7.3。Swift 2.1的解决方案可以在编辑历史中找到。)

传递给 AnySequence init 方法的闭包类型 必须明确指定:

extension SequenceType {
    func take(count:Int) -> AnySequence<Generator.Element> {

        return AnySequence { () -> AnyGenerator<Generator.Element> in
            var generator = self.generate()
            var limit = count
            return AnyGenerator {  
                guard limit > 0 else {
                    return nil
                }
                limit = limit - 1
                return generator.next()
            }
        }
    }
}

请注意,Self.Generator.Element 中的(冗余)Self. 被省略,否则无法编译。

示例:

let sequence = [1,2,3,4,5].take(2)
print(Array(sequence)) // [1, 2]
print(Array(sequence)) // [1, 2]

或者,该方法可以定义为

extension SequenceType {
    func take(count:Int) -> AnySequence<Generator.Element> {

        var generator = self.generate()
        var limit = count

        return AnySequence {
            return AnyGenerator {  
                guard limit > 0 else {
                    return nil
                }
                limit = limit - 1
                return generator.next()
            }
        }
    }
}

现在传递给 AnySequence init 方法的闭包是一个“单表达式闭包”,类型由编译器推断。

但是——正如 David Berry 指出的那样——创建的序列随后表现不同,不能重复调用 generate() 方法 结果相同:

let sequenceX = [1,2,3,4,5].take(2)
print(Array(sequenceX)) // [1, 2]
print(Array(sequenceX)) // []

是允许的行为,如SequenceType protocol reference 中所述:

... It is not correct to assume that a sequence will either be "consumable" and will resume iteration, or that a sequence is a collection and will restart iteration from the first element. A conforming sequence that is not a collection is allowed to produce an arbitrary sequence of elements from the second generator.

因此,人们可以根据所需的行为在这些实现中进行选择。

关于swift - 结合使用 AnySequence 和 anyGenerator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36044959/

相关文章:

swift - 来自base64 url​​的数据

generics - 这个Kotlin转换代码可以简化吗?

python - 无法对通用对象进行猴子修补

ios ble 在 Swift fatal error : Index out of range 中使用 tableview 连接多个设备

Swift 可变集 : Duplicate element found

java - 覆盖下限参数

c# - 通用所有控件方法

java - List<E>.contains(Object),为什么?

ios - UIPickerView 获取另一个 UIPickerView 的值

ios - UIActivityIndi​​cator 随 tableView 滚动