The Swift GeneratorType reference says about the next
method:
next()
Advance to the next element and return it, or nil if no next element exists.
And then in the discussion, it says
Requires:
next()
has not been applied to a copy ofself
since the copy was made, and no preceding call toself.next()
has returnednil
. Specific implementations of this protocol are encouraged to respond to violations of this requirement by callingpreconditionFailure("...")
.
If the Generator is for an Optional type, then it is possible for it to reach a nil
value before reaching the end of the sequence. How does Swift know that it has not reached the end in this case?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With