返回自定义 GeneratorType
Returning a custom GeneratorType
我有一个Class,它应该提供一个基于集合的随机生成器。
因为它是一个随机生成器(next() 永远不会 return nil,除非集合为空),我不希望能够将此生成器用作 sequenceType(不支持 'for in'避免无限循环)
我似乎无法获得正确的方法签名。
这是我构建的框架,其中包括 3 次尝试及其相应的编译器错误。
public protocol myProtocol {
var name : String { get }
}
internal struct myProtocolStruct: myProtocol {
let name : String
init(name: String) {
self.name = name
}
}
internal struct myGenerator : GeneratorType {
let names : [myProtocol]
init(names: [myProtocol]) {
self.names = names
}
mutating func next() -> myProtocol? {
return names.first
}
}
public class myClass {
private var items : [myProtocol]
public init() {
let names = ["0", "1", "2"]
items = names.map{ myProtocolStruct(name: [=10=]) }
}
public func generate0() -> GeneratorType { // error: protocol 'GeneratorType' can only be used as a generic constraint because it has Self or associated type requirements
let x = myGenerator(names: items)
return x
}
public func generate1<C: GeneratorType where C.Element == myProtocol>() -> C {
let x = myGenerator(names: items)
return x // error: 'myGenerator' is not convertible to 'C'
}
public func generate2<C: GeneratorType where C.Element: myProtocol>() -> C {
let x = myGenerator(names: items)
return x // error: 'myGenerator' is not convertible to 'C'
}
}
您可以使用 GeneratorOf
:
/// A type-erased generator.
///
/// The generator for `SequenceOf<T>`. Forwards operations to an
/// arbitrary underlying generator with the same `Element` type,
/// hiding the specifics of the underlying generator type.
///
/// See also: `SequenceOf<T>`.
struct GeneratorOf<T> : GeneratorType, SequenceType { ... }
GeneratorOf
可以从另一个生成器创建(需要
不是 public):
public func generate() -> GeneratorOf<myProtocol> {
return GeneratorOf(myGenerator(names: items))
}
GeneratorOf
也可以直接从表示 next()
函数的闭包中创建:
public func generate() -> GeneratorOf<myProtocol> {
var genItems = self.items // capture the items for use in the closure
return GeneratorOf {
// Return next element, this is just an example which
// returns and removes the first element from the array:
return genItems.count > 0 ? genItems.removeAtIndex(0) : nil
}
}
如果您想要return一个不符合
SequenceType
然后你可以定义对定义的包装器的轻微修改
How is a type-erased generic wrapper implemented?:
public struct GeneratorOnlyOf<T> : GeneratorType {
private let _next:() -> T?
init(_ nextElement: () -> T?) {
_next = nextElement
}
init<G : GeneratorType where G.Element == T>(var _ base: G) {
_next = { base.next() }
}
public mutating func next() -> T? {
return _next()
}
}
然后将 GeneratorOf
替换为 GeneratorOnlyOf
:
public func generate() -> GeneratorOnlyOf<myProtocol> {
return GeneratorOnlyOf(myGenerator(names: items))
}
或者您可以(正如您已经在评论中指出的那样)定义您自己的
非通用 协议:
public protocol MyProtocolGenerator {
mutating func next() -> myProtocol?
}
使您的内部生成器符合该协议:
internal struct myGenerator : MyProtocolGenerator { ... }
然后 return 来自 generate()
方法:
public class myClass {
// ...
public func generate() -> MyProtocolGenerator {
return myGenerator(names: items)
}
}
(旧答案:)generate()
方法 return 是具体的生成器类型,而不是
协议:
func generate() -> myGenerator {
let x = myGenerator(names: items)
return x
}
比较内置Swift类型的生成器,例如
struct Array<T> : MutableCollectionType, Sliceable {
// ...
func generate() -> IndexingGenerator<[T]>
// ...
}
或
struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible {
// ...
func generate() -> DictionaryGenerator<Key, Value>
// ...
}
我有一个Class,它应该提供一个基于集合的随机生成器。
因为它是一个随机生成器(next() 永远不会 return nil,除非集合为空),我不希望能够将此生成器用作 sequenceType(不支持 'for in'避免无限循环)
我似乎无法获得正确的方法签名。
这是我构建的框架,其中包括 3 次尝试及其相应的编译器错误。
public protocol myProtocol {
var name : String { get }
}
internal struct myProtocolStruct: myProtocol {
let name : String
init(name: String) {
self.name = name
}
}
internal struct myGenerator : GeneratorType {
let names : [myProtocol]
init(names: [myProtocol]) {
self.names = names
}
mutating func next() -> myProtocol? {
return names.first
}
}
public class myClass {
private var items : [myProtocol]
public init() {
let names = ["0", "1", "2"]
items = names.map{ myProtocolStruct(name: [=10=]) }
}
public func generate0() -> GeneratorType { // error: protocol 'GeneratorType' can only be used as a generic constraint because it has Self or associated type requirements
let x = myGenerator(names: items)
return x
}
public func generate1<C: GeneratorType where C.Element == myProtocol>() -> C {
let x = myGenerator(names: items)
return x // error: 'myGenerator' is not convertible to 'C'
}
public func generate2<C: GeneratorType where C.Element: myProtocol>() -> C {
let x = myGenerator(names: items)
return x // error: 'myGenerator' is not convertible to 'C'
}
}
您可以使用 GeneratorOf
:
/// A type-erased generator.
///
/// The generator for `SequenceOf<T>`. Forwards operations to an
/// arbitrary underlying generator with the same `Element` type,
/// hiding the specifics of the underlying generator type.
///
/// See also: `SequenceOf<T>`.
struct GeneratorOf<T> : GeneratorType, SequenceType { ... }
GeneratorOf
可以从另一个生成器创建(需要
不是 public):
public func generate() -> GeneratorOf<myProtocol> {
return GeneratorOf(myGenerator(names: items))
}
GeneratorOf
也可以直接从表示 next()
函数的闭包中创建:
public func generate() -> GeneratorOf<myProtocol> {
var genItems = self.items // capture the items for use in the closure
return GeneratorOf {
// Return next element, this is just an example which
// returns and removes the first element from the array:
return genItems.count > 0 ? genItems.removeAtIndex(0) : nil
}
}
如果您想要return一个不符合
SequenceType
然后你可以定义对定义的包装器的轻微修改
How is a type-erased generic wrapper implemented?:
public struct GeneratorOnlyOf<T> : GeneratorType {
private let _next:() -> T?
init(_ nextElement: () -> T?) {
_next = nextElement
}
init<G : GeneratorType where G.Element == T>(var _ base: G) {
_next = { base.next() }
}
public mutating func next() -> T? {
return _next()
}
}
然后将 GeneratorOf
替换为 GeneratorOnlyOf
:
public func generate() -> GeneratorOnlyOf<myProtocol> {
return GeneratorOnlyOf(myGenerator(names: items))
}
或者您可以(正如您已经在评论中指出的那样)定义您自己的 非通用 协议:
public protocol MyProtocolGenerator {
mutating func next() -> myProtocol?
}
使您的内部生成器符合该协议:
internal struct myGenerator : MyProtocolGenerator { ... }
然后 return 来自 generate()
方法:
public class myClass {
// ...
public func generate() -> MyProtocolGenerator {
return myGenerator(names: items)
}
}
(旧答案:)generate()
方法 return 是具体的生成器类型,而不是
协议:
func generate() -> myGenerator {
let x = myGenerator(names: items)
return x
}
比较内置Swift类型的生成器,例如
struct Array<T> : MutableCollectionType, Sliceable {
// ...
func generate() -> IndexingGenerator<[T]>
// ...
}
或
struct Dictionary<Key : Hashable, Value> : CollectionType, DictionaryLiteralConvertible {
// ...
func generate() -> DictionaryGenerator<Key, Value>
// ...
}