我想实现一个自定义可迭代类,它可以包含空元素,类似于[Any?]
。符合SequenceType的大部分规则,但是GeneratorType.next()的约定是当所有元素都被耗尽时应返回nil。这有解决方法吗?
我想实现一个自定义可迭代类,它可以包含空元素,类似于[Any?]
。符合SequenceType的大部分规则,但是GeneratorType.next()的约定是当所有元素都被耗尽时应返回nil。这有解决方法吗?
这是一个(有点傻的)例子:
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博客中有关nil
和Optional(nil)
之间差异及其应用的文章"Optionals Case Study: valuesForKeys"。
更新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)
}
我们可以创建符合SequenceType
协议的对象,这些对象返回Optional
s。然而,因为容易出错,所以在实现您的next()
方法(使用自定义GeneratorType
协议符合的对象)或者实现您的anyGenerator(_:)
闭包参数(使用AnyGenerator
)时,必须非常小心。
一般来说,您应该遵循以下模式:
如果您使用一个符合自定义GeneratorType
协议的对象,并希望它返回Int?
,则必须将next()
方法的返回类型设置为Int??
。AnyGenerator
实例并希望它返回Int?
(AnyGenerator<Int?>
),则必须向您的anyGenerator
方法传递一个闭包,其类型为() -> Int??
。
下面的 Playground 代码受 @Martin R 的回答启发,展示了如何实现一个符合 SequenceType
协议的 Struct
,并使用一个符合 GeneratorType 协议的自定义结构返回
Optional
:
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.None
替换return i % 2 == 0 ? i : Optional<Int>.None
,则您的for循环将不会打印任何内容,您的数组也将为空。
另外请注意,如果您在先前的代码中用return Int?.None
替换return Int??.None
,则会生成一个无限循环的nil
。
使用AnyGenerator
以下Playground代码展示了如何以非常谨慎的方式实现符合SequenceType
协议的Struct
,并使用返回Optional
元素的AnyGenerator
实例:
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)]
前面的序列可以用更简洁但有点不太安全的方式重写:
struct OddSequence: SequenceType {
func generate() -> AnyGenerator<Int?> {
var i = 0
let generator: AnyGenerator<Int?> = anyGenerator {
if i >= 4 { return nil }
i += 1
return i % 2 != 0 ? Optional(nil) : i
}
return generator
}
}