How is a type-erased generic wrapper implemented?

后端 未结 2 1655
渐次进展
渐次进展 2021-01-01 05:37

I need to implement a type-erasing wrapper for my own structure, very similar to SequenceOf, GeneratorOf, etc. So I started by trying to just re-im

相关标签:
2条回答
  • 2021-01-01 06:25

    Here is a sample implementation of MySequenceOf which seems to work:

    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
        }
    }
    

    Example usage:

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

    You can also replace GeneratorOf from the Swift library by the following 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)
        }
    
    }
    

    So (as far as I understand it, and I am far from understanding all the generic sequence and generator stuff) the "trick" is that the next() method of the generator is a closure which captures the given generator and therefore can forward the next() call. A cast is not necessary.

    0 讨论(0)
  • 2021-01-01 06:39

    Try:

    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
        }
    }
    

    The basic strategy of implementing ProtocolOf<T> is, like this:

    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) }
    }
    

    Added to answering @MartinR in comment.

    Is there a special reason that _generate is a closure and not the generator itself?

    First of all, I think, It's a matter of specification or semantics.

    Needless to say, the difference is "when to create the generator".

    Consider this code:

    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)
    

    The problem is: result should be [1,2,3] or [4,5,6]? My MySequenceOf and built-in SequenceOf results the latter. I just matched the behaviors with built-in one.

    0 讨论(0)
提交回复
热议问题