The ? operator - for propagating Result, Option errors.
According to:
https://doc.rust-lang.org/nightly/unstable-book/language-features/try-blocks.html
I can use
let r: Result<i32, std::num::ParseIntError> = try {
"1".parse::<i32>()? };
But I can make use of anonymous function, like that:
let r: Result<i32, std::num::ParseIntError> = (|| -> Result<i32, std::num::ParseIntError> {
Ok("1".parse::<i32>()?) })();
What is the difference, what are pros and cons, and what for to introduce try block if I can achieve the same with anonymous function ?
Schard
April 23, 2025, 10:55am
2
You can also do:
let r: Result<i32, std::num::ParseIntError> = "1".parse::<i32>();
As for your question, the try blocks are syntactic sugar.
Even with only basic optimization, your examples compile to the same assembly:
2 Likes
I wanted to give simple example, perhaps to simple
OK, so this:
let r: Result<i32, std::num::ParseIntError> = "1".parse::<i32>() + "2".parse::<i32>();
will not compile:
cannot add std::result::Result<i32, std::num::ParseIntError>
to std::result::Result<i32, std::num::ParseIntError>
So above examples but a bit more complex:
let r: Result<i32, std::num::ParseIntError> = try {
"1".parse::<i32>()? + "2".parse::<i32>()? };
let r: Result<i32, std::num::ParseIntError> = (|| -> Result<i32, std::num::ParseIntError> {
Ok("1".parse::<i32>()? + "2".parse::<i32>()?) })();
If using try block and anonymous function "is the same" then what for to introduce try block ?
Would not it be better to educate / describe / give examples of how to use anonymous function for that scenario ?
Schard
April 23, 2025, 11:16am
4
This will not compile either. I guess you meant:
let r: Result<i32, std::num::ParseIntError> = try { "1".parse::<i32>()? + "2".parse::<i32>()? };
And it's still the same:
Yes - my mistake that I have just realize.
I have just corrected original examples.
Schard
April 23, 2025, 11:28am
6
Even with non-const values the assembly code of both variants is equivalent:
#![feature(try_blocks)]
#[unsafe(no_mangle)]
fn with_try(a: &str, b: &str) -> Result {
try { a.parse::()? + b.parse::()? }
}
#[unsafe(no_mangle)]
fn with_func(a: &str, b: &str) -> Result {
(|| -> Result {...
You can't interact with the surrounding control flow structure with a closure. E.g. break from a loop, return from the containing function (not the closure).
5 Likes