patternrustMajor
Why is Rust's .expect() called expect?
Viewed 0 times
whyexpectrustcalled
Problem
Rust's
Since so much of Rust is inspired by conventions from functional programming languages, I have been assuming that this is another example of "strange homage to obscurity," but when I asked the Duck it couldn't find an answer for me.
So, I give up. Why is
What is the etymology of this plucky (but fierce!) little member of the standard library?
Edit:
Great news, everyone! After more than a year, we now have both an "explanation" in @GManNickG's tremendously well-researched and documented answer, below, and a "mental model" provided by @Peng's comment and link:
https://doc.rust-lang.org/std/error/index.html#common-message-styles
In short, it is now recommended that diagnostics for
.expect() is one of the most surprising names in the Result/Option space. While unwrap makes sense -- get a value from a Result by "unwrapping" it -- expect is surprisingly counterintuitive (to me).Since so much of Rust is inspired by conventions from functional programming languages, I have been assuming that this is another example of "strange homage to obscurity," but when I asked the Duck it couldn't find an answer for me.
So, I give up. Why is
.expect() the name for Rust's .unwrap_or_panic_with_this_message() function? Is this a reference to a feature in yet another functional language? Is it back-handed shade (or a complement) to Tcl? The result of too many late nights and too much Espresso at Mozilla?What is the etymology of this plucky (but fierce!) little member of the standard library?
Edit:
Great news, everyone! After more than a year, we now have both an "explanation" in @GManNickG's tremendously well-researched and documented answer, below, and a "mental model" provided by @Peng's comment and link:
https://doc.rust-lang.org/std/error/index.html#common-message-styles
In short, it is now recommended that diagnostics for
expect() should be written as "expect...should" or maybe "expect...should have". This makes more sense in the diagnostic output (see the link for examples) but also makes the source code scan better:foo.expect("something bad happened") // NO!
foo.expect("gollywumpus should be current") // YES!Solution
Summary:
No explicit reason for the name is given. However, it is incredibly likely the name comes from the world of parsers, where one "expects" to see a particular token (else the compilation fails).
Within rustc, the use of
Eventually a utility function was added within the compiler that would expect not a specific token or string, but that a given
Personally, I don't find it unusual at all. It's just another verb you can do to the object, like unwrapping or taking or mapping its value. Expecting a value (else, fail) from your
History:
The oldest commit of note is the following:
https://github.com/rust-lang/rust/commit/b06dc884e57644a0c7e9c5391af9e0392e5f49ac
Which adds this function within the compiler:
As far as I can tell, this is the first function named "expect" that deals with inspecting an
If the result of
I encourage you to look at the parser code in this commit - there is extensive use of other
Eventually, the utility of this function was extracted and placed within
https://github.com/rust-lang/rust/commit/e000d1db0ab047b8d2949de4ab221718905ce3b1
Which looked like:
It's worth noting that sometime later, there was eventually an (additional) function named
https://github.com/rust-lang/rust/commit/be3a71a1aa36173ce2cd521f811d8010029aa46f
Over time these were both subsumed by an
https://github.com/rust-lang/rust/commit/0d8f5fa618da00653897be2050980c800389be82
Spoiler for that TODO: that trait no longer exists. It was removed shortly after per:
https://github.com/rust-lang/rust/issues/14008.
More or less this is where we are at today.
I think the most likely conclusion is that the use of
No explicit reason for the name is given. However, it is incredibly likely the name comes from the world of parsers, where one "expects" to see a particular token (else the compilation fails).
Within rustc, the use of
expect-like functions long predate use within Option. These are functions like expect(p, token::SEMI) to expect to parse a semicolon and expect_word(p, "let") to expect to parse the let keyword. If the expectation isn't met, compilation fails with an error message.Eventually a utility function was added within the compiler that would expect not a specific token or string, but that a given
Option contained a value (else, fail compilation with the given error message). Over time this was moved to the Option struct itself, where it remains today.Personally, I don't find it unusual at all. It's just another verb you can do to the object, like unwrapping or taking or mapping its value. Expecting a value (else, fail) from your
Option seems quite natural.History:
The oldest commit of note is the following:
https://github.com/rust-lang/rust/commit/b06dc884e57644a0c7e9c5391af9e0392e5f49ac
Which adds this function within the compiler:
fn expect(sess: session, opt: option, msg: fn() -> str) -> T {
alt opt {
some(t) { t }
none { sess.bug(msg()); }
}
}
As far as I can tell, this is the first function named "expect" that deals with inspecting an
Option. Observe in particular this example use-case within the commit (which was implementing support for class methods!):#debug("looking up %? : %?", def, class_doc);
let the_field = expect(tcx.sess,
decoder::maybe_find_item(def.node, class_doc),
{|| #fmt("get_field_type: in class %?, field ID %? not found",
class_id, def)});
If the result of
decoder::maybe_find_item is None, compilation will fail with the given error.I encourage you to look at the parser code in this commit - there is extensive use of other
expect-esque functions: e.g., expect(p, token::RPAREN) and expect_word(p, "let"). The name of this new function is almost obvious in this environment.Eventually, the utility of this function was extracted and placed within
Option itself:https://github.com/rust-lang/rust/commit/e000d1db0ab047b8d2949de4ab221718905ce3b1
Which looked like:
pure fn expect(opt: option, reason: str) -> T {
#[doc = "
Gets the value out of an option, printing a specified message on failure
# Failure
Fails if the value equals none
"];
alt opt { some(x) { x } none { fail reason; } }
}
It's worth noting that sometime later, there was eventually an (additional) function named
unwrap_expect added in:https://github.com/rust-lang/rust/commit/be3a71a1aa36173ce2cd521f811d8010029aa46f
pure fn unwrap_expect(-opt: option, reason: ~str) -> T {
//! As unwrap, but with a specified failure message.
if opt.is_none() { fail reason; }
unwrap(opt)
}
Over time these were both subsumed by an
Expect trait, which Option implemented:https://github.com/rust-lang/rust/commit/0d8f5fa618da00653897be2050980c800389be82
/// Extension trait for the Option type to add an expect method
// FIXME(#14008) should this trait even exist?
pub trait Expect {
/// Unwraps an option, yielding the content of a Some
///
/// # Failure
///
/// Fails if the value is a None with a custom failure message provided by
/// msg.
fn expect(self, m: M) -> T;
}
Spoiler for that TODO: that trait no longer exists. It was removed shortly after per:
https://github.com/rust-lang/rust/issues/14008.
More or less this is where we are at today.
I think the most likely conclusion is that the use of
expect as a meaningful function name long predates its use in Option. Given it says what it does (expect a value or fail) there is little reason to break the pattern.Context
Stack Overflow Q#66362625, score: 60
Revisions (0)
No revisions yet.