Carl Hung
Carl Hung

Reputation: 555

Self in protocol

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

Answers (1)

0x416e746f6e
0x416e746f6e

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:

  • We declare generic type IndexingGenerator that takes a parameter-type called Elements.
  • This Elements type has a constraint that it must implement Indexable protocol.
  • The generator that we implement is supposed to return values of the type that is accessible via Indexable interface of Elements, which is known to IndexingGenerator via dot-syntax as Elements._Element.
  • Swift infers that 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 a CollectionType.Generator.Element that can be used as IndexingGenerator<T>'s Element. Here we arrange for the CollectionType itself to have an Element type that's deducible from its subscript. Ideally we'd like to constrain this Element to be the same as CollectionType.Generator.Element, but we have no way of expressing it today.

Upvotes: 6

Related Questions