我正在尝试实现SequenceType/GeneratorType示例,并得到一个不太有意义的错误。
这是代码:
// Here's my GeneratorType - it creates a random-number Generator:
struct RandomNumberGenerator:GeneratorType {
typealias Element = Int
mutating func next() -> Element? {
return Int(arc4random_uniform(100))
}
}
当我在Playgrounds中称其为“完美”时:
var randyNum = RandomNumberGenerator()
randyNum.next() // this shows a valid random number in the Gutter
// And calling it from within a println also works:
println("randyNum = \(randyNum.next()!)")
到目前为止,一切都很好。
接下来是SequenceType:
struct RandomNumbersSequence:SequenceType {
typealias Generator = RandomNumberGenerator
var numberOfRandomNumbers:Int
init(maxNum:Int) {
numberOfRandomNumbers = maxNum
}
func generate() -> Generator {
for i in 1...numberOfRandomNumbers {
var randNum = Generator()
randNum.next()
return randNum
}
}
}
那就是产生错误的原因:
'Type RandomNumberSequence' does not conform to protocol 'SequenceType'
。 (Xcode在声明struct RandomNumbersSequence:SequenceType
语句的第一行上显示此错误。)我实际上认为
for
循环的逻辑可能是错误的-意味着我不会得到我想要的结果-但是无论如何,就满足SequenceType
协议(protocol)的要求而言,我认为我做的很对。那么,是什么导致此错误?
最佳答案
这不是生成器的工作方式。假设您要提供一定数量的随机数,则对将最大值作为参数有一个正确的想法,但是您也需要将其存储在生成器中,以及将其存储到哪个状态。
生成器的想法是它存储其状态,并且每次调用next()
时都返回下一个元素。因此,如果要生成最多n
个数字的运行,可以执行以下操作:
struct RandomNumberGenerator: GeneratorType {
let n: Int
var i = 0
init(count: Int) { self.n = count }
mutating func next() -> Int? {
if i++ < n {
return Int(arc4random_uniform(100))
}
else {
return nil
}
}
}
请注意,这里不需要
for
循环。每次调用next()
时,i
都会递增,直到达到最大值,然后生成器才开始返回nil
。SequenceType
的目的是提供新的生成器:struct RandomNumberSequence: SequenceType {
let n: Int
init(count: Int) { self.n = count }
func generate() -> RandomNumberGenerator {
return RandomNumberGenerator(count: n)
}
}
有了这个,您现在可以使用它来生成固定数目的随机整数的序列:
let seq = RandomNumberSequence(count: 3)
for x in seq {
// loops 3 times with x being a new random number each time
}
// every time you use seq, you get a new set of 3 numbers
",".join(map(seq,toString)) // prints 3 comma-separated random nums
// but when you create a generator, it gets “used up”
var gen = seq.generate()
println(gen.next()) // prints a random number
println(gen.next()) // prints another random number
println(gen.next()) // prints the third
println(gen.next()) // prints nil
println(gen.next()) // and will keep printing nil
gen = seq.generate()
println(gen.next()) // will print the first of a new set of 3 numbers
创建这些有状态生成器是一个非常普遍的问题,因此标准库具有一个辅助结构
GeneratorOf
,您可以跳过对它们的定义。需要进行一次闭合,每次调用都应返回下一个要生成的值:struct RandomNumbersSequence: SequenceType {
let maxNum: Int
init(maxNum: Int) { self.maxNum = maxNum }
func generate() -> GeneratorOf<Int> {
// counter to track how many have been generated
var n = 0
return GeneratorOf {
// the closure “captures” n
if n++ < self.maxNum {
return Int(arc4random_uniform(100))
}
else {
return nil
}
}
}
}