[swift-evolution] [Discussion]: Deprecate !-Unwrapping of Optionals

Developer devteam.codafi at gmail.com
Mon Feb 29 07:35:16 CST 2016


That's certainly an interesting stance to take on the issue.  I recently went through a rather large refactoring myself involving mechanically-ported code that had hundreds of force-unwraps left over from Objective-C.  It delighted me to no end to spend days removing them and refactoring the code.  To my mind, each represented an opportunity to explore an alternative means of expressing something very old hat because I would rather not deal with partiality in any way, shape, or form if I didn't have to.  In the end, it was a tough refactoring job because ! was so hard to spot and was a pain to wrestle out of the codebase in some spots.  By the time I merged, there were still spots where it was necessary to use !, but I ended up removing and refactoring hundreds of instances of improperly applied "assumptions" about my code.  Bang, as you said, showed me these cases as false preconditions, but I guess I can't understand why that would be a desirable feature when compared to simply writing the code with other primitives I listed.  Especially because I was working with a library written entirely with objects, what "assertions" we're left still make me incredibly uneasy.

Yes, occasionally you will get cleaner code just making the assertion that something is non-nil, but does that occasion necessitate language-level syntax rather than a stdlib function?  Why not have an unwrap function over an unwrap language feature [because surely the wide range of assertion operators already present in stdlib could use a new counterpart]?

~Robert Widmann

2016/02/29 3:40、Brent Royal-Gordon <brent at architechies.com> のメッセージ:

>> Because of the above, I'd like to start a discussion about its deprecation and eventual removal in favor of either an unsafeUnwrap function or other extra-syntactic constructs.  I don't intend for force-unwrapping as a concept to go away, as there will always be corner cases where it is necessary, but I don't believe it deserves to be so easy to do in a language that holds safety as a core tenant.
> 
> I could not disagree more strongly.
> 
> Swift takes the position that assertions are good and that it's better to crash in an unexpected state than to limp on. Force unwrapping is an example of that philosophy. A force unwrap is a "this is not nil" assertion.
> 
> That assertion often is not appropriate―namely, in code that tests for `nil`―and so we provide, by my count, five general ways to test-and-use nils (pattern matching, optional binding, optional chaining, defaulting, and mapping) without force unwrapping. These features are all great and, with *very* few exceptions, you should always use one of them rather than test-and-force-unwrap.
> 
> But where it *is* appropriate to assert non-nil, *we want you to force unwrap*. If, as you write your code, you are certain a value cannot be nil, we want your code to say so. That way, the code will crash if you're wrong, at the exact point where you made the mistake, where the problem will be easiest to diagnose. We do *not* want you to use a test-and-use construct in a place where you believe the test will always succeed, because you will probably not give any particular attention to the test-failed behavior, so it will probably be wrong.
> 
> In other words, making force unwrapping more difficult will not make people correctly handle unexpected nils―it will make them write code that *undetectably* does the wrong thing by skipping code that wasn't actually meant to be skipped. You'll see fewer crashes but more bugs. That runs counter to Swift's formulation of safety, and I think it would be a serious mistake.
> 
> I recently had the pleasure of debugging some force unwrap crashes in a view controller I hadn't touched in a while. The force unwraps I used very quickly demonstrated to me that my ideas about the code's lifecycle were wrong: for instance, I thought it would never be called before a certain property was set, but it turned out it sometimes was. If I had used a conditional construct without thinking through the consequences, that would have manifested as a mysteriously empty menu which I would have had trouble debugging. By stating explicitly in my code that I believed those values could not be nil, Swift quickly disproved my belief, showed me exactly what was wrong, and prompted me to correct it. That's the best thing it could have done for me in this situation.
> 
> I often see Swift style guides suggest that force-unwrapping is a strong code smell and should always be avoided, but I think that's wrongheaded. Test-and-force-unwrap *is* a code smell, and force-unwrap-when-you're-not-really-sure is incorrect too. But when you *are* sure, force unwrap is the very best way to write your code, because it will make any mistakes immediately obvious.
> 
> That's a feature, not a bug.
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 


More information about the swift-evolution mailing list