The Swift GeneratorType reference says about the next
method:
next()
Advance to the next element and return it, or nil if no ne
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
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 {
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
and the ?
syntax for declaring optionals is likewise a convenient shortcut for Optional
. Consider that the following two lines are equivalent in every manner except the variable name:
let foo = Optional.None
let bar: Int? = nil