我正在尝试实现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
            }
        }
    }
}

09-29 19:59