Swift 序列类型不工作
Swift SequenceType not working
我正在尝试实现一个 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()!)")
到目前为止一切顺利。
接下来是序列类型:
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
协议的要求,我想我说对了。
那么是什么导致了这个错误?
您看到的错误消息:
'Type RandomNumberSequence' does not conform to protocol 'SequenceType'
始终意味着您的 class 或结构缺少协议声明为必需的内容。
在这种情况下,我们缺少 generate() -> Generator
方法。 "But, it's right there!"你说呢?好吧,它是,但它没有编译。
func generate() -> Generator {
for i in 1...numberOfRandomNumbers {
var randNum = Generator()
randNum.next()
return randNum
}
}
问题是,如果你用 numberOfRandomNumbers
小于或等于 0
来初始化你的结构怎么办?您的循环执行零次并且 generate
不能 return 任何东西。
我不确定究竟你想在这个循环中做什么逻辑,但我们可以通过简单地添加一个 return 声明将 return a Generator
:
func generate() -> Generator {
for i in 1...numberOfRandomNumbers {
var randNum = Generator()
randNum.next()
return randNum
}
return Generator()
}
这不会完成您想要完成的事情。这不是发电机应该如何工作。但它将修复 generate() -> Generator
方法并允许您的结构现在符合协议。
这不是发电机的工作原理。
生成器的想法是它存储它的状态,每次你调用 next()
你 return 下一个元素。因此,如果你想生成最多 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
递增,直到达到最大值,然后生成器开始 returning 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
,它允许您跳过定义它们。它需要一个闭包,每次调用它都应该 return 下一个要生成的值:
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
}
}
}
}
使用 Swift 3,您可以选择三种 RandomNumbersSequence
实现中的一种来解决您的问题。
1。使用符合Sequence
协议的结构和符合IteratorProtocol
协议的结构
以下 Playground 代码展示了如何实现符合 Sequence
的 RandomNumbersSequence
结构并使用符合 IteratorProtocol
协议的 RandomNumbersIterator
结构:
import Darwin // required for arc4random_uniform
struct RandomNumbersIterator: IteratorProtocol {
let maxNum: Int
var n = 0
init(maxNum: Int) {
self.maxNum = maxNum
}
mutating func next() -> Int? {
n += 1
return n <= self.maxNum ? Int(arc4random_uniform(10)) : nil
}
}
struct RandomNumbersSequence: Sequence {
let maxNum: Int
init(maxNum: Int) {
self.maxNum = maxNum
}
func makeIterator() -> RandomNumbersIterator {
return RandomNumbersIterator(maxNum: maxNum)
}
}
用法#1:
for value in RandomNumbersSequence(maxNum: 3) {
print(value)
}
/*
may print:
5
7
3
*/
用法#2:
let randomArray = Array(RandomNumbersSequence(maxNum: 3))
print(randomArray)
/*
may print: [7, 6, 1]
*/
用法 #3:
let randomSequence = RandomNumbersSequence(maxNum: 3)
var randomGenerator = randomSequence.makeIterator()
randomGenerator.next() // may return: 4
randomGenerator.next() // may return: 8
randomGenerator.next() // may return: 3
randomGenerator.next() // will return: nil
2。使用符合 Sequence
和 IteratorProtocol
协议的结构
以下 Playground 代码展示了如何实现符合 Sequence
和 IteratorProtocol
协议的 RandomNumbersSequence
结构:
import Darwin // required for arc4random_uniform
struct RandomNumbersSequence: Sequence, IteratorProtocol {
let maxNum: Int
var n = 0
init(maxNum: Int) {
self.maxNum = maxNum
}
mutating func next() -> Int? {
n += 1
return n <= self.maxNum ? Int(arc4random_uniform(10)) : nil
}
}
用法#1:
for value in RandomNumbersSequence(maxNum: 3) {
print(value)
}
/*
may print:
5
7
3
*/
用法#2:
let randomArray = Array(RandomNumbersSequence(maxNum: 3))
print(randomArray)
/*
may print: [7, 6, 1]
*/
用法 #3:
var randomSequence = RandomNumbersSequence(maxNum: 3)
randomSequence.next() // may return: 4
randomSequence.next() // may return: 8
randomSequence.next() // may return: 3
randomSequence.next() // will return: nil
3。使用 AnyIterator
和符合 Sequence
的结构
作为先前实现的替代方案,您可以使用 AnyIterator<T>
作为符合 Sequence
协议的结构中 makeIterator
方法的 return 类型。以下 Playground 代码显示了如何使用 RandomNumbersSequence
结构实现它:
import Darwin // required for arc4random_uniform
struct RandomNumbersSequence: Sequence {
let maxNum: Int
init(maxNum: Int) {
self.maxNum = maxNum
}
func makeIterator() -> AnyIterator<Int> {
var n = 0
let iterator: AnyIterator<Int> = AnyIterator {
n += 1
return n <= self.maxNum ? Int(arc4random_uniform(10)) : nil
}
return iterator
}
}
用法#1:
for value in RandomNumbersSequence(maxNum: 3) {
print(value)
}
/*
may print:
5
7
3
*/
用法#2:
let randomArray = Array(RandomNumbersSequence(maxNum: 3))
print(randomArray)
/*
may print: [7, 6, 1]
*/
用法 #3:
let randomSequence = RandomNumbersSequence(maxNum: 3)
let randomGenerator = randomSequence.makeIterator()
randomGenerator.next() // may return: 4
randomGenerator.next() // may return: 8
randomGenerator.next() // may return: 3
randomGenerator.next() // will return: nil
我正在尝试实现一个 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()!)")
到目前为止一切顺利。
接下来是序列类型:
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
协议的要求,我想我说对了。
那么是什么导致了这个错误?
您看到的错误消息:
'Type RandomNumberSequence' does not conform to protocol 'SequenceType'
始终意味着您的 class 或结构缺少协议声明为必需的内容。
在这种情况下,我们缺少 generate() -> Generator
方法。 "But, it's right there!"你说呢?好吧,它是,但它没有编译。
func generate() -> Generator { for i in 1...numberOfRandomNumbers { var randNum = Generator() randNum.next() return randNum } }
问题是,如果你用 numberOfRandomNumbers
小于或等于 0
来初始化你的结构怎么办?您的循环执行零次并且 generate
不能 return 任何东西。
我不确定究竟你想在这个循环中做什么逻辑,但我们可以通过简单地添加一个 return 声明将 return a Generator
:
func generate() -> Generator {
for i in 1...numberOfRandomNumbers {
var randNum = Generator()
randNum.next()
return randNum
}
return Generator()
}
这不会完成您想要完成的事情。这不是发电机应该如何工作。但它将修复 generate() -> Generator
方法并允许您的结构现在符合协议。
这不是发电机的工作原理。
生成器的想法是它存储它的状态,每次你调用 next()
你 return 下一个元素。因此,如果你想生成最多 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
递增,直到达到最大值,然后生成器开始 returning 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
,它允许您跳过定义它们。它需要一个闭包,每次调用它都应该 return 下一个要生成的值:
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
}
}
}
}
使用 Swift 3,您可以选择三种 RandomNumbersSequence
实现中的一种来解决您的问题。
1。使用符合Sequence
协议的结构和符合IteratorProtocol
协议的结构
以下 Playground 代码展示了如何实现符合 Sequence
的 RandomNumbersSequence
结构并使用符合 IteratorProtocol
协议的 RandomNumbersIterator
结构:
import Darwin // required for arc4random_uniform
struct RandomNumbersIterator: IteratorProtocol {
let maxNum: Int
var n = 0
init(maxNum: Int) {
self.maxNum = maxNum
}
mutating func next() -> Int? {
n += 1
return n <= self.maxNum ? Int(arc4random_uniform(10)) : nil
}
}
struct RandomNumbersSequence: Sequence {
let maxNum: Int
init(maxNum: Int) {
self.maxNum = maxNum
}
func makeIterator() -> RandomNumbersIterator {
return RandomNumbersIterator(maxNum: maxNum)
}
}
用法#1:
for value in RandomNumbersSequence(maxNum: 3) {
print(value)
}
/*
may print:
5
7
3
*/
用法#2:
let randomArray = Array(RandomNumbersSequence(maxNum: 3))
print(randomArray)
/*
may print: [7, 6, 1]
*/
用法 #3:
let randomSequence = RandomNumbersSequence(maxNum: 3)
var randomGenerator = randomSequence.makeIterator()
randomGenerator.next() // may return: 4
randomGenerator.next() // may return: 8
randomGenerator.next() // may return: 3
randomGenerator.next() // will return: nil
2。使用符合 Sequence
和 IteratorProtocol
协议的结构
以下 Playground 代码展示了如何实现符合 Sequence
和 IteratorProtocol
协议的 RandomNumbersSequence
结构:
import Darwin // required for arc4random_uniform
struct RandomNumbersSequence: Sequence, IteratorProtocol {
let maxNum: Int
var n = 0
init(maxNum: Int) {
self.maxNum = maxNum
}
mutating func next() -> Int? {
n += 1
return n <= self.maxNum ? Int(arc4random_uniform(10)) : nil
}
}
用法#1:
for value in RandomNumbersSequence(maxNum: 3) {
print(value)
}
/*
may print:
5
7
3
*/
用法#2:
let randomArray = Array(RandomNumbersSequence(maxNum: 3))
print(randomArray)
/*
may print: [7, 6, 1]
*/
用法 #3:
var randomSequence = RandomNumbersSequence(maxNum: 3)
randomSequence.next() // may return: 4
randomSequence.next() // may return: 8
randomSequence.next() // may return: 3
randomSequence.next() // will return: nil
3。使用 AnyIterator
和符合 Sequence
的结构
作为先前实现的替代方案,您可以使用 AnyIterator<T>
作为符合 Sequence
协议的结构中 makeIterator
方法的 return 类型。以下 Playground 代码显示了如何使用 RandomNumbersSequence
结构实现它:
import Darwin // required for arc4random_uniform
struct RandomNumbersSequence: Sequence {
let maxNum: Int
init(maxNum: Int) {
self.maxNum = maxNum
}
func makeIterator() -> AnyIterator<Int> {
var n = 0
let iterator: AnyIterator<Int> = AnyIterator {
n += 1
return n <= self.maxNum ? Int(arc4random_uniform(10)) : nil
}
return iterator
}
}
用法#1:
for value in RandomNumbersSequence(maxNum: 3) {
print(value)
}
/*
may print:
5
7
3
*/
用法#2:
let randomArray = Array(RandomNumbersSequence(maxNum: 3))
print(randomArray)
/*
may print: [7, 6, 1]
*/
用法 #3:
let randomSequence = RandomNumbersSequence(maxNum: 3)
let randomGenerator = randomSequence.makeIterator()
randomGenerator.next() // may return: 4
randomGenerator.next() // may return: 8
randomGenerator.next() // may return: 3
randomGenerator.next() // will return: nil