SE-0217 - The "Unwrap or Die" operator

(Dave DeLong) #62

Again, you're assuming that we have infinite time to devote to making sure every proposal we put up is updated every time we think about it. This is a false assumption. Please stop assuming your know the intimate details of our lives and why we do (or do not) update things.

(Xiaodi Wu) #63

If the proposal was put up for review without consent of the authors, I hope you'll take that up with the review manager. I assume nothing other than that what I'm reading is what the authors wish me to read, and that it's a sincere effort at putting forward the best possible argument for incorporating the feature, and I review it on that basis. Nowhere do I make any demand that you put in "infinite time" and I'm quite taken aback that you're attacking me personally for doing my best to give feedback.

(Dave DeLong) #64

One thing I've been considering the past couple of days is:

Is there a reasonable other use of a !! operator?

The only other use of a double-bang, as far as I'm aware, is the Double Factorial operator in mathematics. I think we would all easily agree that it is highly unlikely that Swift would ever add that operator to the standard library, given its limited use, and also given that we don't (indeed, can't) have a factorial operator (!-as-factorial would conflict with !-to-unwrap).

Thus, combined with the logic for why the !! was chosen in the first place (it is symmetrical to the use of ? and ??, when associated with !-to-unwrap), it seems like !!-to-unwrap-or-die seems like the only logical use of the operator within the Swift language.

And if we agree on that (that !! only makes sense to exist as "unwrap or die"), then why not add it for completeness to the language? No one would be forcing anyone to use a purely-additive change, and for those of us that use it regularly, it's Nice to have one-less-thing we have to maintain ourselves in our "make-up-for-the-standard-library's-shortcomings" libraries.

(Xiaodi Wu) #65

This is a line of argumentation that comes up quite often, and in my opinion it's misguided. Any addition of operators (which like keywords are hard to look up) requires all users to learn about it and to be able to understand code that's written which uses the operator. There's more to "use" than merely writing it into one's own code.

Now, of course, if its absence from the standard library is demonstrably a "shortcoming," then there's a good argument for its addition, but I think the crux of the issue here is that the proposal hasn't convinced me that the absence of the operator is such a shortcoming. Absent that, "why not add it" is not a strong argument for making even an additive change.

(Joe Groff) #66

It's my fault for not warning you in advance, sorry about that. I'll make a point of doing so for future reviews.

@xwu Please try to make your points without personally questioning the authors' or other users' motivations.


I'm not sure I understand the strong pushback against this proposal.

If looks like people who wouldn't use the double bang operator want to prevent others from using it. Is it a reasonable way to look at a proposal?

To me, !! has a great potential for becoming idiomatic Swift in education, tutorials, sample code, etc, which favor code balance between the dry and austere purity of !, and the verbosity of guard which can be distracting. Distraction and too much implicits are two real hazards that !! quite elegantly avoids.

if segue.identifier == "detail" {
    let indexPath = tableView.indexPathForSelectedRow
        !! "selection must be set in tableView:didSelectRowAtIndexPath:"

The code above is better than a guard ... else { return }, because one should not teach how to ignore programmer errors.

The code above is better than a guard ... else { fatalError("...") } because the tutorial topic is table views and segues, not Swift control flow.

The code above is better than indexPathForSelectedRow! because you can't morally write a tutorial with a dry bang.

Those are genuine qualities of this proposal that deserve kudos.

(Pushkar N Kulkarni) #68

I agree with this. One of the things I love Swift for is its clear and intuitive syntax. In that context, I don't find wrappedValue !! β€œmessage” intuitive enough.

(Ben Cohen) #69

The RHS of !! can still be a function call that tees information to another destination before returning the string to trap on, if you want that behavior.

(Xiaodi Wu) #70

I'm sorry that @davedelong feels that his motives were questioned.

Again, to re-emphasize, my meaning is the exact opposite. Some months earlier, when asked for feedback, I made a particular critique of the proposal as it was then written. The same issue persists to this day, and @brentdax asked whether this was an issue with the proposal or with the feature proposed. My response is that, on the basis of presuming that the authors are capable people who work diligently and give due consideration to feedback, the persistence of the issue reflects a problem with the feature proposed.

To be honest, I am quite upset that the response from @davedelong is to attack me for making the presumption that he and his co-authors gave due consideration to the feedback, on the grounds that making that presumption is demanding his "infinite time." To my mind, it is a presumption of good faith that we all have to make of proposal authors.


No. Not at all.

We want to keep the standard library trim and svelte.

If people want to use !! in their own code, they can easily define it themselves.

(Dave DeLong) #72

No, β€œwe” do not. I want the standard library to be as full featured and rich as possible.

If I wanted a minimal language I’d use C.

(Xiaodi Wu) #73

Although you may disagree, the official statement about what "we" want is to keep the standard library small:

We believe that the Swift standard library should remain small and laser-focused on providing support for language primitives.

Indeed, at least in 2017, you yourself acknowledged that this was a goal of the standard library.

(Pierpaolo Frasa) #74

The amount of emotional involvement in this thread (on both sides) is indeed slightly puzzling.

If this doesn't make the cut, ?? + Never can always be hand-rolled and used instead (I for one am glad for this thread, because I didn't even realise that was a possibility). If this does get included, nobody is forced to use it. It's not like Swift would radically become a different language.

It also seems like different people have very different ways of dealing with errors in their code, which is fair, so the question is whether Swift should stay opinionated or allow for a wider range of expression in this regard.

(Joe Groff) #75

This is a pretty classic non-apology, it turns the blame around on the other person for their feelings, and following it up with a tit-for-tat attack on the other person is not a good idea. You don't need to defend yourself or even apologize at all necessarily, please just be mindful of the fact of how invoking other people's motivations can be perceived, and keep the discussion focused on the proposal.

(David Hart) #76

I am slightly -1 on this proposal. All the points I want to make have been done before. I'll just summarise that while I am sympathetic with the goal of the proposal, I am worried about a few points:

  • it doesn't allow for customisation (logging, etc..) like a ?? Never solution would
  • it is not entirely clear for beginners that the String is purely for diagnostics like fatalError would

The problem addressed is significant enough to warrant a change, but I still think this might not be the right solution.

Like said previously, I think it doesn't fit the customisation and clarity aspects of Swift.


An in-depth reading of the different arguments.

(Xiaodi Wu) #77

@Joe_Groff, to be clear, I publicly apologized immediately and directly to @davedelong, and made it clear that causing offense was not my intention:

I then explained how my critique was directed at the ideas proposed and not at his or anyone else's motivations, and that I assumed only the best of intentions. Let me say again that I am very hurt by @davedelong's reply. I was accused of the following, which no fair reading of what I wrote could support:

This is not some sort of tit-for-tat ploy; I really am upset. I spent the better part of the morning crafting a detailed response to contribute to the discussion, trying to make my points as clearly as possible, and I have explained what I meant as clearly as I could.

(Joe Groff) #78

I would say the question of "standard library trim" is largely irrelevant to the merits of this specific proposal. No matter what, the standard library is responsible for "providing support for language primitives" as @xwu pointed out, and since this proposal is pitched as becoming an idiomatic way of handling unexpected nils, going so far as propose changes to fixits to use the new operator, it's arguably vying to become one of those primitives. The role and scope of the standard library is an interesting question I think we have some work to do to clarify, but I don't think that discussion belongs in this review thread.

(Benjamin Mayo) #79

I'm in support of adding !! β€” and I generally err on the conservative side when it comes to growing the standard library. I can see places in my apps and frameworks where I would like to be able to annotate the force-unwraps with a more descriptive message. I know I am guilty of just writing value! in the past because I was too lazy to write out guard let x = optional else { fatalError("descriptive reason") }.

I think some of the proposal examples are spurious, like the let context = UIGraphicsGetCurrentContext() !! "drawRect context guarantee was breached" example is more appropriately handled by ! IMO, but this is probably subjective and I assume Swift documentation is not based off contributor proposal examples. As fix-its are pseudo-documentation in themselves, I would prefer that !! be added and not have the default fix-it changed from ! β€” at least make it the second option in the list of fix-it options. I worry that it would get it in the way, and generally annoy people who know what they are doing. Fix-its are not a source compatibility issue so being conservative here doesn't really have a downside.

I greatly prefer a specially denoted operator, !! , than the Never-bottom type idea of value ?? fatalError(...). That feels far too tricksy for me, and code that β€” to my eyes at least β€” looks fancy rather than obvious. And a point of pure elegance in favour, I like being able to use my eyes to scan with Ctrl-F ! and get a rough sense of where the 'trapdoors' in a piece of code are. !! supports that convenience further.

I was chewing over the lack of customisation concern brought up by others up-thread, but I was satisfied with @Ben_Cohen's response that a custom logging function could interoperate well with !! as-is, essentially acting as middleware and ultimately passing the error message as the return value to type-check with the operator.

(Erica Sadun) #80

This point keeps coming up on this thread and I'd like to address it. We offer !! Never as an alternate. It is wordier because of fatalError() but retains the right semantics (!! is the "or die" operator vs ?? as the "or fallback value" operator).

Would you (and others) change your vote if the Core Team went with !! Never over !! String?

(Brent Royal-Gordon) #81

Sorry, something I forgot to mention in my previous review:

Rather than being implemented with fatalError(), I believe !! should be implemented with preconditionFailure(). This would make it match the behavior of !, which cheats for speed in -Ounchecked but traps and prints a message in -O. That means it won't print the message in -Ounchecked, but if you're using that mode, you should be prepared to get exactly what you asked for whether you like it or not.

(I consider this to be correcting a minor mistake in the proposal, not proposing an alternative. I still support the expr !! "message" syntax over the alternative with an explicit call on the right side, and one reason I prefer it is because !! preconditionFailure("...") is longer and less obvious than !! fatalError("...") even though it's probably what you should be doing.

Also, another reason is that !! Never means you have to learn what the various functions which can go on the right side do and when you should use each one. That's bad for language learners, for much the same reason public static void main(String[] args) is bad for learners.)