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