I have been struggling to properly implement the ForwardIndexType
protocol for an enum, in particular the handling of the end case (i.e for the last item without a successor). This protocol is not really covered in the Swift Language book.
Here is a simple example
enum ThreeWords : Int, ForwardIndexType {
case one=1, two, three
func successor() ->ThreeWords {
return ThreeWords(rawValue:self.rawValue + 1)!
}
}
The successor()
function will return the next enumerator value, except for the last element, where it will fail with an exception, because there is no value after .three
The ForwardTypeProtocol
does not allow successor()
to return a conditional value, so there seems to be no way of signalling that there is no successor.
Now using this in a for loop to iterate over the closed range of all the possible values of an enum, one runs into a problem for the end case:
for word in ThreeWords.one...ThreeWords.three {
print(" \(word.rawValue)")
}
println()
//Crashes with the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Swift inexplicably calls the successor()
function of the end value of the range, before executing the statements in the for loop. If the range is left half open ThreeWords.one..<ThreeWords.three
then the code executes correctly, printing 1 2
If I modify the successor function so that it does not try to create a value larger than .three
like this
func successor() ->ThreeWords {
if self == .three {
return .three
} else {
return ThreeWords(rawValue:self.rawValue + 1)!
}
}
Then the for loop does not crash, but it also misses the last iteration, printing the same as if the range was half open 1 2
My conclusion is that there is a bug in swift's for loop iteration; it should not call successor()
on the end value of a closed range. Secondly, the ForwardIndexType
ought to be able to return an optional, to be able to signal that there is no successor for a certain value.
Has anyone had more success with this protocol ?
Indeed, it seems that successor
will be called on the last value.
You may wish to file a bug, but to work around this you could simply add a sentinel value to act as a successor.
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