You guessed it. It's another unwrap rant.
The biggest problems are:
It's just code clutter and hurts readability - could have post parenthesis marker like u, such as get_data()u; and that u represents that the compiler needs to add .unwrap() there, but it should be different for option and result so maybe s for some and r for result - something like that.
You don't know if the call to unwrap is for an option or result - should be separated! Very poor readability.
Most of my .unwrap() usage is in testing code…everywhere else does either ? or .map_err(ErrType::variant_ctor_func). Or .expect("if this fires, the source is wrong") (e.g., in-source regex parses).
As for readability…I think method chaining is cleaner than a (bespoke) syntax sugar thing. Would it only work for Option and Result? How would user types opt-in to having a returns_user_type()u thing happen? Is it just making a method called "unwrap" special? Though it seems you'd prefer to have it be type-specific even…so I have no idea how user types would get this. And one of the really nice things about Rust (to me) is that Option and Result are just plain library code (no magic). Try is still compiler magic for non-nightly uses…but that is still "just a trait" once it is available.
As for bots…how does one measure their appreciation?
I recommend its use. I use it in regex, regex-syntax, regex-automata, csv, bstr, ripgrep, jiff and pretty much every crate I've ever published.
See Using unwrap() in Rust is Okay - Andrew Gallant's Blog for more elaboration on my position. (I feel like I link this too much, but then again, I wrote it precisely because I kept repeating myself. So now I can just link to that.)
I fully agree with your position on unwrap(). I usually just don't go into so much detail, because I mainly see .unwrap() overused (my theory is that learning materials and docs use unwrap() a lot for brevity, and this makes use of .unwrap() seem more normal and common than it should be).
If I want to simplify the advice, I think it's better to simplify it towards using too little .unwrap() than too much.
I passed that whole thing a long time ago regarding the differences, but there's lots of tutorials with unwrap and people see it and say "that's not readable code" (then go to another language). You don't see it later on. For those looking into rust, it's one of those things just like "MyNewStr".to_string() - lolol
I also pretty much agree with @burntsushi 's blog post. To summarize what it says: it is appropriate to use unwrap or expect when
you have an operation that returns a Result or Option
if this operation fails (returns Err or None), that indicates a bug in the program
it is impractical to restructure the program so that the failure can be proven impossible at compile time
And I think that those rules provide an indirect rebuttal to @JeffG's request for shorter notation for unwrap. It is not "just code clutter and hurts readability". It is a warning sign: here is a place where the program might have a bug, and we couldn't find a good way to make the compiler prove it doesn't, so humans should pay closer attention to the code in this area. It should stand out, for the same reason we make unsafe blocks and annotations stand out.
For that same reason I prefer expect over unwrap (outside of tests). It means that there is at least some documentation on why I thought this could not happen in practice.
There is a clippy lint that can be set up for this, to warn on unwrap but not expect. I'm on my phone so I won't provide an example, but it shouldn't be hard to find.
In the same spirit as // SAFETY comments, I often write a justifying comment for many of my unwraps and expects to explain why the error case is unreachable. Then when it inevitably panics on an edge case, I can go review the comment to see where my past self's reasoning went wrong.
You just see it more clearly.
Like when something is returned from a function call, and then you call unwrap or ? on the result - what am I calling unwrap or ? on.
Option and Result are two VERY DIFFERENT domains with the same methods - only adds confusion.
I think what I was getting at with this post wasn't so much picking on unwrap versus ?
It's that there is a LOT that could be implicit by nature, and this could be implicit by nature, and toggled via setting in cargo.toml project settings with additional configuration like which operator to use when implicit.
So there would be like an "implicit_mode" setting - by default it's off.
When you turn it on, the following will become implicit assuming the variation declaration is explicit, or rust otherwise has the context needed to make it happen:
? is implicit. (or unwrap if chosen)
into() is implicit
.to_string() is implicit (when var is mut)
etc
Additionally, for times when you only want implicit mode in certain modules, or blocks, could have a module level derive macro that will simply surround the module with implicit{} block, and also an inline "implicit{}" block for fine level control of sections of code without resorting to module or project level (cuz the *** didn't want it).
To me .unwrap() on both does the same thing — gets the inner value or panics. I don't see them as very different.
? is constrained on the return type of the function. You can't use it on Option when the function returns Result, you have to convert it first with .ok_or(err) or similar, and vice-versa with .ok(). To use ? you will need to know whether the function returns Option or Result, but I don't see how that could be improved by having separate methods like .unwrap_option() and .unwrap_result() — you would still need to know the type returned by the function to know which one to call.
So there would be like an "implicit_mode" setting - by default it's off
You're describing a solution, but I still don't see what problem that solution is supposed to fix. There are many different reasons for things to be explicit:
Despite the usual dogma that they are semantically different, I don't really see them as semantically different at all, more like Option is a special case: Option<T> = Result<T, ()>. It's a result with no error attached when missing. I wish it was defined like that because I often need to convert between the two types and it's hard to remember the two different APIs. Consider u32::checked_add: it could have returned Result<u32, Overflow>, but it returns Option<u32> because Overflow would have been a ZST anyway.
As long as we are not talking about using them for storing things they both represent the idea of failing computation with the only difference that Option doesn't care why the computation failed while Result does. In this context ? is a monadic bind operator and the behavior is exactly the same for both. Both unwrap and expect means "I know this computation succeeds, get the result out, if not - there's a problem with the code", with the difference that expects allows you to explain why things succeed.
Semantically different.
I mean, they are different domains.
They both happen to be enum driven.
One is (essentially) a container for a value, which may or may not be there.
One is a (essentially) a container for a function result
Very different things. Just because they are enum driven doesn't mean the language should tie them together in some weird way.
The language gets all tangled with these 2 things (doesn't happen in other languages)
The semantics of both .unwrap() and .expect() are "consume the container and return the value contained within, and if that's not possible then panic", with .expect() having the additional semantics of printing a message when it panics.
Importantly, that holds equally for both Option<T> and Result<T, E>.
You seem to be using them as such, which is fair enough.
But to reduce those types to merely that is selling them short I my view: I have used Result<T, E> as a field type before (that is, for storage purposes), and if I deem it necessary, I'll do it again.
Similarly, I have also used Option<T> both as a function result, and as the type of a fieldstruct field.
To me the only difference is "do I want to differentiate between different forms of 'value not present'?".
If so, I use a Result. If not, an Option.
Could you give some examples of what you mean by this? I ask because to me they're fairly neatly separated.
Please note that the question of adding any shorthand operator/syntax, (or implicit rules) for doing .unwrap() is explicitly something that’s unlikely to happen according to the Language team, and there’s a recommendation that proposals of such nature [there’s a whole list] would need to look into prior discussions and address the existing concerns
If something appears on this page, that doesn't mean Rust would never consider making any similar change. It does mean that any hypothetical successful proposal to do so would need to address at a minimum all of these known concerns, whether by proposing a new and previously unseen approach that avoids all the concerns, or by making an extraordinary case for why their proposal outweighs those concerns.
Hopeful proposers of any of these ideas should document their extensive research into the many past discussions on these topics and ensure they have something new to offer.
If we aren’t only talking about new syntax, the idea of
You don't know if the call to unwrap is for an option or result - should be separated!
could still seem relevant in the context of changes to the method names in the standard library…
…except that can’t work either: unwrap is an existing, stable, and very widely used API, it can’t be changed.
So the question of how related or not Option and Result are is not really that relevant at all, in case it discussed only for the purpose evaluating such proposals.
It just doesn't LOOK like other languages.
It gets all tangled up here. It does.
You gotta keep in mind that many people in tech are switching learning many different things.
Regarding the shorthand, not sure what you were referring to exactly, but I'm saying that it should be as implicit as possible.
The language is WAY TOO VERBOSE.
Compare with python - night and day.
having an implicit mode where things like ? weren't even needed, would be better imho