组合使用AnySequence和anyGenerator

时间:2016-03-16 19:13:46

标签: 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内联)吗?

1 个答案:

答案 0 :(得分:4)

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

传递给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() } } } } init方法的闭包类型 必须明确指定:

Self.

请注意Self.Generator.Element中的(冗余)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

现在传递给generate() init方法的闭包是一个&#34;单表达式闭包&#34;并且类型由编译器推断。

但是 - 正如David Berry所说 - 创建的序列表现不同,let sequenceX = [1,2,3,4,5].take(2) print(Array(sequenceX)) // [1, 2] print(Array(sequenceX)) // [] 方法不能重复调用 结果相同:

# create needed indexes
idx1 <- !(nchar(df$RE) == 1 & nchar(df$AL) == 1)
idx2 <- (nchar(df$RE) > nchar(df$AL)) + 1L
idx3 <- (nchar(df$RE) < nchar(df$AL)) + 1L

# replace the values
df$RE[idx1] <- c('D','I')[idx2][idx1]
df$AL[idx1] <- c('D','I')[idx3][idx1]

是允许的行为,如SequenceType protocol reference

中所述
  

......假设一个序列要么是不正确的   &#34;自耗&#34;并将重新开始迭代,或者序列是a   收集并将从第一个元素重新开始迭代。一个   允许不是集合的符合序列产生   来自第二个生成器的任意元素序列。

因此,可以在这些实现中进行选择,具体取决于所需的行为。