I am learning swift and playing with Xcode. and I always dig into the definitions. I have seen that:
public protocol GeneratorType {
typealias Element
@warn_unused_result
public mutating func next() -> Self.Element?
}
A struct that conforming this protocol:
public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType {
public init(_ elements: Elements)
public mutating func next() -> Elements._Element?
}
I know 'Self' means that returning the conforming type. But what does 'Self.Element' mean? and the function that implemented the requirement that returning 'Elements._Element?', I can’t see 'Elements._Element?' is equal to 'Self.Element?'. Can anyone explain to me this? and tell me more about this. thank you.
Self.Element refers to the concrete type that any type implementing GeneratorType protocol will declare as its Element typealias.
For example, in this generator of Fibonacci numbers:
struct Fibonacci: GeneratorType {
typealias Element = Int
private var value: Int = 1
private var previous: Int = 0
mutating func next() -> Element? {
let newValue = value + previous
previous = value
value = newValue
return previous
}
}
... you implement GeneratorType protocol and indicate what will be its Element typealias (Int in this case), and that's the type that generator's next() will be returning (well, actually the optional of that type).
Quite often, though, you would not have to explicitly specify typealiases when implementing parametrised protocols, as Swift is smart enough to infer them for you. E.g. for the Fibonacci numbers generator from the above example the following will also do:
struct Fibonacci: GeneratorType {
private var value: Int = 1
private var previous: Int = 0
mutating func next() -> Int? {
let newValue = value + previous
previous = value
value = newValue
return previous
}
}
... Swift knows from the signature of next() that it returns Int?, and that GeneratorType implementors also must have next() in their to-do list, and that these methods must return Element? types. So, Swift just puts 2 and 2 together, and infers that Element? must be the same thing as Int?, and therefore Element == Int.
About this:
public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType {
public init(_ elements: Elements)
public mutating func next() -> Elements._Element?
}
Here we have four things going on:
IndexingGenerator that takes a parameter-type called Elements.Elements type has a constraint that it must implement Indexable protocol.Indexable interface of Elements, which is known to IndexingGenerator via dot-syntax as Elements._Element.Element of IndexingGenerator is the same thing as Elements._Element.So, essentially the above delclaration is equivalent to:
public struct IndexingGenerator<Elements : Indexable> : GeneratorType, SequenceType {
public typealias Element = Elements._Element
public init(_ elements: Elements)
public mutating func next() -> Element?
}
Finally, if curious why _Element and not just Element like in GeneratorType, here is what they write in the open-source Swift repository (under swift/stdlib/public/core/Collection.swift):
The declaration of
_Elementand subscript here is a trick used to break a cyclic conformance/deduction that Swift can't handle. We need something other than aCollectionType.Generator.Elementthat can be used asIndexingGenerator<T>'sElement. Here we arrange for theCollectionTypeitself to have anElementtype that's deducible from its subscript. Ideally we'd like to constrain thisElementto be the same asCollectionType.Generator.Element, but we have no way of expressing it today.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With