我想实现一个可以包含nil元素的自定义可迭代类,类似于[Any?]
。符合SequenceType大部分都有效,除了GeneratorType.next()
的契约表示当所有元素都已用完时它应该返回nil。有解决方法吗?
答案 0 :(得分:13)
这是一个(非常愚蠢)的例子:
struct OddSequence : SequenceType {
func generate() -> GeneratorOf<Int?> {
var current = 0
return GeneratorOf<Int?>() {
if current >= 6 {
return nil
}
current++
if current % 2 == 0 {
return current
} else {
return Optional(nil)
}
}
}
}
for x in OddSequence() {
println(x)
}
输出:
nil
Optional(2)
nil
Optional(4)
nil
Optional(6)
生成器为每个元素返回一个可选项(可以是Optional(nil)
),
如果序列用尽,则nil
。
另请参阅Swift博客中的"Optionals Case Study: valuesForKeys",了解nil
和之间的区别
Optional(nil)
及其应用程序。
Swift 2的更新:
struct OddSequence : SequenceType {
func generate() -> AnyGenerator<Int?> {
var current = 0
return anyGenerator {
if current >= 6 {
return nil
}
current++
if current % 2 == 0 {
return current
} else {
return Optional(nil)
}
}
}
}
for x in OddSequence() {
print(x)
}
答案 1 :(得分:0)
可以创建返回SequenceType
s的Optional
协议符合对象。但是,因为它很容易出错,所以在实现next()
方法(使用自定义GeneratorType
协议符合对象)或实现anyGenerator(_:)
闭包参数时必须非常谨慎(使用AnyGenerator
)。
根据经验,您应该始终遵循以下模式:
如果您使用自定义
GeneratorType
协议符合对象并希望它返回Int?
,则必须将next()
方法的返回类型设置为Int??
。以同样的方式,如果您使用
AnyGenerator
实例并希望它返回Int?
(AnyGenerator<Int?>
),则必须传递() -> Int??
类型的闭包到anyGenerator
方法。
以下Playground代码受@Martin R的回答启发,展示了如何实现符合SequenceType
Struct
协议的GeneratorType
协议与自定义Optional
协议一致的结构返回{ {1}} S:
struct OddGenerator: GeneratorType {
var i = 0
mutating func next() -> Int?? {
if i >= 4 {
return Int??.None
//return Optional.None // also works
//return nil // also works
}
i += 1
return i % 2 == 0 ? i : Optional<Int>.None
//return i % 2 == 0 ? Optional.Some(i) : Int?.None // also works
//return i % 2 == 0 ? .Some(i) : .Some(Optional<Int>.None) // also works
//return i % 2 == 0 ? Optional(i) : Optional(nil) // also works
}
}
struct OddSequence: SequenceType {
func generate() -> OddGenerator {
return OddGenerator()
}
}
for x in OddSequence() {
print(x)
}
/*
prints:
nil
Optional(2)
nil
Optional(4)
*/
let array = Array(OddSequence())
print(array) // prints: [nil, Optional(2), nil, Optional(4)]
请注意,如果您使用return i % 2 == 0 ? i : Optional<Int>.None
替换上一代码中的return i % 2 == 0 ? i : Optional.None
,则for循环将不会打印任何内容,并且您的数组将为空。
另请注意,如果您使用return Int??.None
替换上一代码中的return Int?.None
,则会生成nil
的无限循环。
AnyGenerator
以下Playground代码显示了如何以非常谨慎的方式实现符合SequenceType
的{{1}}协议与返回Struct
元素的AnyGenerator
实例:
Optional
以前的序列可以用非常简洁但种安全性较低的方式重写:
struct OddSequence: SequenceType {
func generate() -> AnyGenerator<Optional<Int>> {
var i = 0
let generator: AnyGenerator<Optional<Int>> = anyGenerator {
() -> Optional<Optional<Int>> in
if i >= 4 { return Optional<Optional<Int>>.None }
i += 1
return i % 2 != 0 ?
Optional<Optional<Int>>.Some(Optional<Int>.None) :
Optional<Optional<Int>>.Some(Optional<Int>.Some(i))
}
return generator
}
}
for x in OddSequence() {
print(x)
}
/*
prints:
nil
Optional(2)
nil
Optional(4)
*/
let array = Array(OddSequence())
print(array) // prints: [nil, Optional(2), nil, Optional(4)]