如何实现类型擦除的通用包装器?

时间:2014-11-09 19:44:53

标签: swift generics

我需要为自己的结构实现类型擦除包装,非常类似于SequenceOfGeneratorOf等。所以我开始尝试重新实现标准{{1}我自己。

我刚复制过&粘贴SequenceOf的声明,将其重命名为SequenceOf,并填写一些存根以获取:

MySequenceOf

我收到编译错误:&#34; 同类型中的任何一种类型都不是指泛型参数或相关类型&#34;。所以我假设Xcode生成的/// A type-erased sequence. /// /// Forwards operations to an arbitrary underlying sequence with the /// same `Element` type, hiding the specifics of the underlying /// sequence type. /// /// See also: `GeneratorOf<T>`. struct MySequenceOf<T> : SequenceType { /// Construct an instance whose `generate()` method forwards to /// `makeUnderlyingGenerator` init<G : GeneratorType where T == T>(_ makeUnderlyingGenerator: () -> G) { fatalError("implement me") } /// Construct an instance whose `generate()` method forwards to /// that of `base`. init<S : SequenceType where T == T>(_ base: S) { fatalError("implement me") } /// Return a *generator* over the elements of this *sequence*. /// /// Complexity: O(1) func generate() -> GeneratorOf<T> { fatalError("implement me") } } &#39; SequenceOf&#34;约束真的意味着&#34; where T == T&#34;,它给了我以下可编译的结构:

where G.Element == T

现在,很简单,我只需要从初始化程序中挂起struct MySequenceOf<T> : SequenceType { init<G : GeneratorType where G.Element == T>(_ makeUnderlyingGenerator: () -> G) { fatalError("implement me") } func generate() -> GeneratorOf<T> { fatalError("implement me") } } 并从makeUnderlyingGenerator调用它:

generate()

但这给了我错误:&#34; &#39; G&#39;不能转换为&#39; GeneratorOf&#39; &#34;

如果强制演员, 会编译:

struct MySequenceOf<T> : SequenceType {
    let maker: ()->GeneratorOf<T>

    init<G : GeneratorType where G.Element == T>(_ makeUnderlyingGenerator: () -> G) {
        self.maker = { return makeUnderlyingGenerator() }
    }

    func generate() -> GeneratorOf<T> {
        return self.maker()
    }
}

但是它在运行时从动态演员表中崩溃了。

那么如何实现这样的类型擦除呢?它必须是可能的,因为Swift标准库做了很多(SequenceOf,GeneratorOf,SinkOf)。

2 个答案:

答案 0 :(得分:5)

尝试:

struct MySequenceOf<T> : SequenceType {
    private let _generate:() -> MyGeneratorOf<T>

    init<G : GeneratorType where G.Element == T>(_ makeUnderlyingGenerator: () -> G) {
        _generate = { MyGeneratorOf(makeUnderlyingGenerator()) }
    }

    init<S : SequenceType where S.Generator.Element == T>(_ base: S) {
        _generate = { MyGeneratorOf(base.generate()) }
    }

    func generate() -> MyGeneratorOf<T> {
        return _generate()
    }
}

struct MyGeneratorOf<T> : GeneratorType, SequenceType {

    private let _next:() -> T?

    init(_ nextElement: () -> T?) {
        _next = nextElement
    }

    init<G : GeneratorType where G.Element == T>(var _ base: G) {
        _next = { base.next() }
    }

    mutating func next() -> T? {
        return _next()
    }

    func generate() -> MyGeneratorOf<T> {
        return self
    }
}

实施ProtocolOf<T>基本策略是这样的:

protocol ProtocolType {
    typealias Value
    func methodA() -> Value
    func methodB(arg:Value) -> Bool
}

struct ProtocolOf<T>:ProtocolType {
    private let _methodA: () -> T
    private let _methodB: (T) -> Bool

    init<B:ProtocolType where B.Value == T>(_ base:B) {
        _methodA = { base.methodA() }
        _methodB = { base.methodB($0) }
    }

    func methodA() -> T { return _methodA() }
    func methodB(arg:T) -> Bool { return _methodB(arg) }
}

添加在评论中回答@MartinR。

  

有一个特殊的原因,即_generate是一个闭包而不是发生器本身?

首先,我认为,这是规范或语义问题。

毋庸置疑,不同之处在于“何时创建发电机”。

考虑以下代码:

class Foo:SequenceType {
    var vals:[Int] = [1,2,3]
    func generate() -> Array<Int>.Generator {
        return vals.generate()
    }
}

let foo = Foo()
let seq = MySequenceOf(foo)
foo.vals = [4,5,6]
let result = Array(seq)

问题是:result应为[1,2,3]还是[4,5,6]?我的MySequenceOf和内置SequenceOf会导致后者。我只是将行为与内置行为相匹配。

答案 1 :(得分:1)

以下是MySequenceOf的示例实现,似乎有效:

struct MySequenceOf<T> : SequenceType {

    let myGenerator : GeneratorOf<T>

    init<G : GeneratorType where G.Element == T>(_ makeUnderlyingGenerator: () -> G) {
        self.myGenerator = GeneratorOf( makeUnderlyingGenerator() )
    }

    init<S : SequenceType where S.Generator.Element == T>(_ base: S) {
        self.myGenerator = GeneratorOf( base.generate() )
    }

    func generate() -> GeneratorOf<T> {
        return myGenerator
    }
}

使用示例:

let seq = MySequenceOf {
    _ -> GeneratorOf<Int> in
    var i = 0
    return GeneratorOf {
        i < 5 ? ++i : nil
    }
}
for i in seq  { println(i) }

您还可以通过以下方法从Swift库中替换GeneratorOf MyGeneratorOf

struct MyGeneratorOf<T> : GeneratorType, SequenceType {

    var nextFunc : () -> T?

    init<G : GeneratorType where G.Element == T>(_ base: G) {
        self.nextFunc = {
            () -> T? in
            var generator = base
            return generator.next()
        }
    }

    init(_ nextElement: () -> T?) {
        self.nextFunc = nextElement
    }

    mutating func next() -> T? {
        return nextFunc()
    }

    // Returns a copy of itself.
    func generate() -> MyGeneratorOf<T> {
        return MyGeneratorOf(nextFunc)
    }

}

所以(据我所知,我远非了解所有通用序列 和发电机的东西)&#34;技巧&#34;是next()的方法 发电机是一个闭合器,捕获给定的发电机,因此可以 转发next()电话。不需要演员表。