返回自定义 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>
    // ...
}