How is a type-erased generic wrapper implemented?

后端 未结 2 1668
渐次进展
渐次进展 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:39

    Try:

    struct MySequenceOf : SequenceType {
        private let _generate:() -> MyGeneratorOf
    
        init(_ makeUnderlyingGenerator: () -> G) {
            _generate = { MyGeneratorOf(makeUnderlyingGenerator()) }
        }
    
        init(_ base: S) {
            _generate = { MyGeneratorOf(base.generate()) }
        }
    
        func generate() -> MyGeneratorOf {
            return _generate()
        }
    }
    
    struct MyGeneratorOf : GeneratorType, SequenceType {
    
        private let _next:() -> T?
    
        init(_ nextElement: () -> T?) {
            _next = nextElement
        }
    
        init(var _ base: G) {
            _next = { base.next() }
        }
    
        mutating func next() -> T? {
            return _next()
        }
    
        func generate() -> MyGeneratorOf {
            return self
        }
    }
    

    The basic strategy of implementing ProtocolOf is, like this:

    protocol ProtocolType {
        typealias Value
        func methodA() -> Value
        func methodB(arg:Value) -> Bool
    }
    
    struct ProtocolOf:ProtocolType {
        private let _methodA: () -> T
        private let _methodB: (T) -> Bool
    
        init(_ 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.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.

提交回复
热议问题