另一个问题本质上是问如何实现一个 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)
}
}
但似乎我应该能够使用 AnySequence
和 anyGenerator
在我的 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()
})
})
}
}
不幸的是,这会产生多个输入错误,主要是(我认为)因为类型推断失败。
有人对如何让这个(使用 AnySequence
和 anyGenerator
内联)工作有任何建议吗?
最佳答案
(现在的答案是基于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/