I also thought I would be strongly for this when i started reviewing, now I am certainly less clear from reading comments.
Backing up, and looking at how I want to deal with a fatal situation while force unwrapping. I think the inherent terseness of !
is a problem, it is too easily added, and if you are in a hurry trying to compile something sometimes it is often just thrown in there, lurking to eventually cause a crash. I would like this proposal to essentially make a replacement for !
in most cases. Linters would look for single !
and suggest other alternatives.
Now if we go with !!
, having to specify, potentially a long string, every time you need to access something that may fail, we have maybe gone too far the other way. The happy path is no longer the emphasis and the negative path becomes overwhelming.
Comparing this to the alternatives such as using guard let
this is definitely a step in the right direction, having to have curly braces, indents, and fatal error are quite cumbersome. Many are inclined to not bother with it because it takes more time to write, and it interrupts the flow of the code with indents etc. So from that perspective, I think it is better than the options we have now.
So I think we definitely need to have a single line solution that does not require braces, which is accomplished with both !!
and ?? fatalError("message")
The question which is best of these, and is the failure case getting too much of the attention? From this perspective the !!
is the most terse, and the `?? fatalError("message)" is more clear.
I think I would be happy with either of these solutions, but I am left with, is there a solution that could make the happy path not subordinate to the failure path. Maybe not having a string there would be better? What if had an enum with our failures? This would make it so you could move the error description up out of the main line of code.
enum Failure: Fatalities {
case urlMustNotBeNil
case expectedFileIsMissing
}
let url = URL(string: "messedupurl") !! .urlMustNotBeNil
let file = Data(contentsOf: "missing file") !! .expectedFileIsMissing
Fatalities
would be a protocol, and then get automatic completion so all you would need is the .urlMustNotBeNil
this would be similar to the Error
protocol. The !!
would only allow the Fatalities
protocol. (I have not name-smithed the protocol name). I think this fits more in the spirit of the exception handing in Swift. This also makes the solution even more terse without giving up the clarity of fatalError
thus balancing out the happy path, and the failure path as equals. Also, if you have the same reason more than once, you don't have to repeat the same string over and over. If you want more detailed explanations the enum can implement string
enum Failure: String, Fatalities {
case urlMustNotBeNil = "URL Must Not Be Nil"
case expectedFileIsMissing = "Expected File Is Missing"
}
TLDR: So, this is a suggested change to the proposal. The main change, just allow implementers of the Fatalities
protocol on the right hand side of the !!
rather than a string. It would work similar to Error
protocol.