Reputation: 555
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.
Upvotes: 3
Views: 1024
Reputation: 10136
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
_Element
and subscript here is a trick used to break a cyclic conformance/deduction that Swift can't handle. We need something other than aCollectionType.Generator.Element
that can be used asIndexingGenerator<T>
'sElement
. Here we arrange for theCollectionType
itself to have anElement
type that's deducible from its subscript. Ideally we'd like to constrain thisElement
to be the same asCollectionType.Generator.Element
, but we have no way of expressing it today.
Upvotes: 6