To unwrap or not to unwrap?

I am very much a beginner in Rust. I have read through the Rust book and a couple of other tutorials.

I have an important (but possibly very basic) question, about when to use unwrap(). It is very commonly used in example code or tutorials, because it is a 'quick solution' to take something out of Option or Result values.

However, it does feel somewhat 'dirty' to do so, because you are converting a pattern match possibility to a run-time panic. The documentation of Option.unwrap() also states this:

In general, because this function may panic, its use is discouraged. Instead, prefer to use pattern matching and handle the None case explicitly.

Besides unwrap(), expect('Whoops! I didnt think about this case.') is used a lot in tutorials as well.

Now I wonder: In proper application or library code, how are these cases actually handled? Are there a lot more pattern matches? Or is it actually rather common to say "Well, my program cannot work properly anymore when this stuff goes different than expected, so I just panic"?.

This is probably something that you might only get a feeling for after a lot of practice and practical experience, but I hope some of you might give some advise/tips on how to approach this.

4 Likes

The problem is that unwrap used to be the most straightforward thing to do when a short example was ran in fn main. However, it's not necessary anymore as a main function can now return a Result. For example.

use std::fs::File;
use std::io::{self, prelude::*};

fn main() -> io::Result<()> {
    let mut file = File::open("/etc/passwd")?;
    let mut vec = Vec::new();
    file.read_to_end(&mut vec)?;
    io::stdout().write_all(&vec)?;
    Ok(())
}

The preferred way to handle errors would be to use failure crate. Also please check its documentation.

This answer used to recommend error-chain crate, however it's not a recommended way to handle errors anymore. The old post contents are available by clicking the history button in this post's header.

6 Likes

Another pattern to use when dealing with Options is to use an if let Some(...) to do something if there was a value, otherwise you continue as normal. An example of this is in a crate I'm working on for generating documents programatically (here). You can optionally provide an author and title for the document, so I'm using an if let statement to write the author/title fields only if they were provided.

Otherwise there's always unwrap_or() and unwrap_or_else() if it makes sense to use a default value when you get a None. There's also ok_or() for converting an Option into a Result which you can then use ? on to return early.

You aren't always confined to using pattern matching to deal with errors properly, often Result and Option (and a lot of other types) will give you convenient methods for converting to other types or dealing with the "negative" (e.g. Err and None) variants.

2 Likes

Don't unwrap.

An easy alternative is to use the ? operator and Result<…, Box<dyn Error>> as function's return type. Box<dyn Error> is the most generic error type (sort of like a base class), so most error types are compatible with it and you don't have to implement code for conversions yourself.

use std::error::Error;

fn foo() -> Result<(), Box<dyn Error>> {
   let unwrapped_file = std::fs::File::open("file")?;

   let optional = Some(1);
   let unwrapped = optional.ok_or("Error - expected Some, but got None")?;
}
7 Likes

In the Rust cookbook we disallow unwrap. A note about error handling explains how to use ? in realistic example code.

2 Likes

To unwrap or not to unwrap. That is the question.

Avoid unwrap whenever possible. If not possible, question everything.

4 Likes

Thank you very much, everyone, for these great answers! I had no idea that there were so many other tools to handle the Option and Result types in a nice way. :smiley:

Why avoid unwrap on an option when you are sure that what are you looking for is there?
I mean, for example, when I take something from a GTK builder it must be there.

I think this is a clear case of when not to follow the rule. In programming, never follow a rule because it is a rule, but because the trade-off of following the rule vs. not following it is favorable in the specific situation you are considering.

I guess that if you already know that something is there, you can simply use unwrap(). In basic situations, this will not happen as it means that the thing you are using has no reason to use an Option<T> or Result<T> over a plain T, but of course there are situations in which you have been able to check an invariant in another way meaning you are, on a rational level that is outside of what the compiler can infer, certain that something is true.

Many of the smart, fast algorithms out there use this to be more efficient.

Some other examples might be the cases where you are sure that some iteration is not empty because you know for certain that it is infinite, or where you are certain that a multithreading race condition cannot take place because of how/when you (don't) access it, when you use sentinels (an Elephant in Cairo) when searching for something in a collection, etc.

1 Like

Avoid unwrap whenever possible. If not possible, question everything.

This inspired me to write a story in the style of the Codeless code.

I call it...

impl From<CandyError> for RaspberryCandyError

The novice was disquieted.

He held in his hands what was—most likely—a cube-shaped, raspberry-flavored hard confectionary wrapped in an opaque, crimson-red wrapper with the confectioner's branding.

However, there was also the possibility that he held a small, well-polished, cube-shaped stone inscribed with a short message apologizing for the "terrible harvest this year," and pleading for life—and wrapped in an opaque, crimson-red wrapper with the confectioner's branding.

Worse yet was the possibility that he held a cube-shaped hard confectionery of any flavor that isn't raspberry, wrapped in—well, you get the idea.

In any case, his task was to deliver this object to the emperor. And suffice it to say, the emperor enjoys raspberry, and does not enjoy insolence. It is not a favorable position to be the one who hands a lemon-flavored treat to the emperor's aide.

How can I be certain that this object meets the emperor's specification?

He could test it, but the emperor also likes to receive his candy still wrapped its protective cellophane coating; especially now, in the dusty season.

The novice went to the garden to reflect on these harsh circumstances.


In the garden he found a young monk furnished in the robes of The Wandering Order of the Mighty M.[1] Nobody of any obvious importance, but an acolyte. The novice was very fortunate.

"Perhaps you can help me," the novice introduced himself. "I am aware your people have devised methods for making decisions based upon the contents of a wrapper. I have here a candy, and need to know if it is raspberry-flavored."

"To be clear; does your behavior need to change if the flavor isn't raspberry?," the acolyte inquired.

"It is a gift to the emperor. If it isn't raspberry, then I would perhaps wish to deliver an apology instead."

"I see. Then you must become one with the wrapper."

The novice considered this for a moment, but could not hide his frustration. "You speak in riddles!"

"I only speak in truth! As soon as you receive knowledge of the contents of the wrapper, your state becomes entangled with it." He could see his words were getting lost on the novice. "Are you familiar with Schrodinger's Cat?"

The sun bore down on the novice's neck. Time is getting short; the delivery is to take place in just two, maybe three --release builds![2] "Perhaps we can discuss this later?," the novice pleaded.

Though technically not a question, it received an answer; but by a third voice, in the direction of the pond. "The discussion will take place now... Without allusion to cats." It was the Master, seated on a rock in the lotus position, facing away from the pair. His calm, enlightened voice somehow penetrated the entire garden, and reached them as though he were sitting a mere frog's leap away.[3]

"Since you need to know, then surely, you have no choice but to try it."

The novice tore off the crimson wrapper to reveal a solid cube of what was definitely not stone, and held it in front of his nose. Closing his eyes, he could just barely recognize the familiar scent of...

"Ah... raspb—"

(THWACK)

The treat flew out of the novice's hand as he received a powerful smack to the back of the head, temporarily throwing him into a world of dazzling stars, falling candy and unstable geometry. Slowly, the three images in front of him began to resolve back into one, and as he squinted, he could make out that the cube had safely fallen right into the prepared, open hand of the Mighty M acolyte, where it sat now along with the fallen remnants of the wrapper.

Their eyes met; The acolytes' went cross.

"You tore it!"

"???" The novice could only speak in punctuation at this point.

"The wrapper! You tore the wrapper!" The acolyte lifted a fragment from his palm and waggled it around. "How will you become one with this?"

The novice's heart sank. "I... don't know. I'm sorry. I guess I unwrap-ed it too aggressively?"

The master's voice penetrated the air once more. "You already know the answer to that."

"But what is more," the Master continued; "you are a Carrier. Your solution lies not in that wrapper, but here." He reached into his lap and held up a dark, palm-sized square shape, and without a further gesture, the pair were beckoned. Approaching more closely, the dark square resolved to a cellophane wrapper; one of the deepest violet and emblazoned with the text "RASPBERRY." Pristine and unfolded, without a crease in sight, ready to be wrapped around anything small and cube-like.

"A... slightly different wrapper?" The words were slowly forced out by the Mighty M acolyte as he started to become dizzy, and fell to the ground unconscious. The novice did not notice, as he was too stunned at the implications of what the master held. Nonetheless, the novice tried to contain himself; and calmly asked,

"Master... you foresaw my arrival?"

"Nonsense. I just read your signature."


[1]: This is not an unusual sight, as the Wandering Order are known to frequently visit the lands of other programming languages. (They also make one hell of a curry.)

[2]: This is without incremental compilation, of course.

[3]: For reference, the garden is about a score of armspans, square.

9 Likes

Thank you Konrad for the research and for updating your explanation.