How do Generators whose Element is Optional know when they've reached the end?

后端 未结 1 1260
囚心锁ツ
囚心锁ツ 2020-12-21 03:19

The Swift GeneratorType reference says about the next method:

next() Advance to the next element and return it, or nil if no ne

相关标签:
1条回答
  • 2020-12-21 04:00

    It's important to note that whatever type a generator is generating, it wraps that type in an optional.

    The GeneratorType protocol declares an associated type which it calls Element and a method, next(), whose return type is of type Element?. Whatever Element is, next() wraps it in an optional (and remember, optional is just an enum).

    So a generator generating optionals wraps those optionals in another optional layer.

    Consider the following:

    let array: [Int?] = [1, 2, nil, 4, nil, nil, 7, 8, nil, nil, 11]
    

    This is an array of optional integers.

    So if we call generate() on this array, it will give us something that returns type Optional<Optional<Int>> or Int?? from the next() method.

    The first two calls to next will give us values (1, then 2). The third looks like it returns nil:

    But effectively this is just misleading information. Realistically, the third return is actually this: Optional.Some(nil)

    We can see that there are more values to generate by looking at this while loop, which is terminated by the real nil that is generated after 11:

    All of the nil values we see print are actually Optional.Some(nil), and when the next() call finally returns Optional.None, the loop terminates.

    What we're looking at here is the difference between the following three values possible values:

    let optionalSomeValue: Int?? = 3
    let optionalSomeNil: Int?? = Optional.Some(nil)
    let optionalReallyNil: Int?? = nil
    

    Note that the second line could also be written as:

    let optionalSomeNil: Int?? = Optional.Some(Optional.None)
    

    At the end of the day, we have to keep in mind that optional is just a generic enum:

    enum Optional<T> {
        case Some(T)
        case None
    }
    

    There is no restriction on what T can be, which means it can itself be an optional, and it could be an optional with case None.

    In Swift, the nil keyword is just a convenient shortcut for Optional<T>.None and the ? syntax for declaring optionals is likewise a convenient shortcut for Optional<T>.Some. Consider that the following two lines are equivalent in every manner except the variable name:

    let foo = Optional<Int>.None
    let bar: Int? = nil
    

    0 讨论(0)
提交回复
热议问题