2014-11-09 3 views
4

Мне нужно реализовать оболочку для стирания стилей для моей собственной структуры, очень похожую на SequenceOf, GeneratorOf и т. Д. Поэтому я начал с того, что попытался просто повторно реализовать стандарт SequenceOf.Как реализуется стандартная оболочка типа стирания?

Я просто скопировал & pasteed в декларации для SequenceOf, переименовал его в MySequenceOf и заполняли в некоторых пнях, чтобы получить:

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

Я получаю ошибку компиляции: "Ни типа в том же типа относится к общему параметру или связанному типу ". Таким образом, я предполагаю, что Xcode сгенерированных декларация SequenceOf «s„where T == T“ограничение на самом деле означает„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():

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

, но это дает мне ошибку: «„G“не конвертируется в„GeneratorOf“»

Это делает компилирует, если я заставляю бросок:

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

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

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

Но тогда он выходит из строя во время выполнения из динамического гипсе.

Итак, как можно реализовать стирание типа? Это должно быть возможно, потому что стандартная библиотека Swift делает это связкой (SequenceOf, GeneratorOf, SinkOf).

+0

Попробуйте определить тип генератора для вашего типа. –

+1

«Итак, я предполагаю, что объявление Xcode, созданное в соответствии с инструкцией SequenceOf« где T == T », действительно означает« где G.Element == T »« Да, это известная ошибка в том, как объявление отображается в Xcode , Вы не можете сказать 'где T == T', и заголовок Swift на самом деле не говорит об этом. – matt

ответ

4

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

Стратегия внедрения 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 в комментарии.

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

Прежде всего, я думаю, это вопрос спецификации или семантики.

Излишне говорить, что разница - «когда создавать генератор».

Рассмотрим этот код:

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 приводит к последнему. Я просто сопоставлял поведение со встроенным.

+0

Я взял меня на некоторое время, чтобы выяснить свой ответ, но я должен признать, что ваш взгляд выглядит более аккуратным. Есть ли специальная причина, по которой '_генерация' является закрытием, а не самой генератором (как в моем коде)? –

+1

@MartinR Добавлено в ответ. И как примечание, см. Это: https://github.com/andelf/Defines-Swift/blob/14a3c623278344cb433b80fb4197f1a64f52d5ad/Swift.swift#L3837 – rintaro

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

Вы также можете заменить GeneratorOf от Swift библиотеки следующим 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) 
    } 

} 

Итак, насколько я понимаю, и я далек от понимания всей общей последовательности и генератора), «трюк» заключается в том, что генератор генератора представляет собой замыкание, которое захватывает данный генератор и поэтому может переадресуйте вызов next(). Приведение не требуется.

Смежные вопросы