<buttonid="sidebar-toggle"class="icon-button"type="button"title="Toggle Table of Contents"aria-label="Toggle Table of Contents"aria-controls="sidebar">
<inputtype="search"id="searchbar"name="searchbar"placeholder="Search this book ..."aria-controls="searchresults-outer"aria-describedby="searchresults-header">
<p>There is an even shorter way to deal with <code>Result</code> (and <code>Option</code>), shorter than <code>match</code> and even shorter than <code>if let</code>. It is called the "question mark operator", and is just <code>?</code>. After a function that returns a result, you can add <code>?</code>. This will:</p>
<ul>
<li>return what is inside the <code>Result</code> if it is <code>Ok</code></li>
<li>pass the error back if it is <code>Err</code></li>
</ul>
<p>In other words, it does almost everything for you.</p>
<p>We can try this with <code>.parse()</code> again. We will write a function called <code>parse_str</code> that tries to turn a <code>&str</code> into a <code>i32</code>. It looks like this:</p>
let parsed_number = input.parse::<i32>()?; // Here is the question mark
Ok(parsed_number)
}
fn main() {}
</code></pre></pre>
<p>This function takes a <code>&str</code>. If it is <code>Ok</code>, it gives an <code>i32</code> wrapped in <code>Ok</code>. If it is an <code>Err</code>, it returns a <code>ParseIntError</code>. Then we try to parse the number, and add <code>?</code>. That means "check if it is an error, and give what is inside the Result if it is okay". If it is not okay, it will return the error and end. But if it is okay, it will go to the next line. On the next line is the number inside of <code>Ok()</code>. We need to wrap it in <code>Ok</code> because the return is <code>Result<i32, ParseIntError></code>, not <code>i32</code>.</p>
<p>Now, we can try out our function. Let's see what it does with a vec of <code>&str</code>s.</p>
let failure = "Not a number".parse::<i32>();
failure.rbrbrb(); // ⚠️ Compiler: "What is rbrbrb()???"
}
</code></pre></pre>
<p>The compiler doesn't understand, and says:</p>
<pre><codeclass="language-text">error[E0599]: no method named `rbrbrb` found for enum `std::result::Result<i32, std::num::ParseIntError>` in the current scope
--> src\main.rs:3:13
|
3 | failure.rbrbrb();
| ^^^^^^ method not found in `std::result::Result<i32, std::num::ParseIntError>`
</code></pre>
<p>So <code>std::result::Result<i32, std::num::ParseIntError></code> is the signature we need.</p>
<p>We don't need to write <code>std::result::Result</code> because <code>Result</code> is always "in scope" (in scope = ready to use). Rust does this for all the types we use a lot so we don't have to write <code>std::result::Result</code>, <code>std::collections::Vec</code>, etc.</p>
<p>We aren't working with things like files yet, so the ? operator doesn't look too useful yet. But here is a useless but quick example that shows how you can use it on a single line. Instead of making an <code>i32</code> with <code>.parse()</code>, we'll do a lot more. We'll make an <code>u16</code>, then turn it to a <code>String</code>, then a <code>u32</code>, then to a <code>String</code> again, and finally to a <code>i32</code>.</p>
let parsed_number = input.parse::<u16>()?.to_string().parse::<u32>()?.to_string().parse::<i32>()?; // Add a ? each time to check and pass it on
Ok(parsed_number)
}
fn main() {
let str_vec = vec!["Seven", "8", "9.0", "nice", "6060"];
for item in str_vec {
let parsed = parse_str(item);
println!("{:?}", parsed);
}
}
</code></pre></pre>
<p>This prints the same thing, but this time we handled three <code>Result</code>s in a single line. Later on we will do this with files, because they always return <code>Result</code>s because many things can go wrong.</p>
<p>Imagine the following: you want to open a file, write to it, and close it. First you need to successfully find the file (that's a <code>Result</code>). Then you need to successfully write to it (that's a <code>Result</code>). With <code>?</code> you can do that on one line.</p>
<p>The message <code>"Time to panic!"</code> displays when you run the program: <code>thread 'main' panicked at 'Time to panic!', src\main.rs:2:3</code></p>
<p>You will remember that <code>src\main.rs</code> is the directory and file name, and <code>2:3</code> is the line and column name. With this information, you can find the code and fix it.</p>
<p><code>panic!</code> is a good macro to use to make sure that you know when something changes. For example, this function called <code>prints_three_things</code> always prints index [0], [1], and [2] from a vector. It is okay because we always give it a vector with three items:</p>
<p>It prints <code>8, 9, 10</code> and everything is fine.</p>
<p>But imagine that later on we write more and more code, and forget that <code>my_vec</code> can only be three things. Now <code>my_vec</code> in this part has six things:</p>
let my_vec = vec![8, 9, 10, 10, 55, 99]; // Now my_vec has six things
prints_three_things(my_vec);
}
</code></pre></pre>
<p>No error happens, because [0] and [1] and [2] are all inside this longer <code>Vec</code>. But what if it was really important to only have three things? We wouldn't know that there was a problem because the program doesn't panic. We should have done this instead:</p>
<p>This gives us <code>thread 'main' panicked at 'my_vec must always have three items', src\main.rs:8:9</code>. Thanks to <code>panic!</code>, we now remember that <code>my_vec</code> should only have three items. So <code>panic!</code> is a good macro to create reminders in your code.</p>
<p>There are three other macros that are similar to <code>panic!</code> that you use a lot in testing. They are: <code>assert!</code>, <code>assert_eq!</code>, and <code>assert_ne!</code>.</p>
<p>Here is what they mean:</p>
<ul>
<li><code>assert!()</code>: if the part inside <code>()</code> is not true, the program will panic.</li>
<li><code>assert_eq!()</code>: the two items inside <code>()</code> must be equal.</li>
<li><code>assert_ne!()</code>: the two items inside <code>()</code> must not be equal. (<em>ne</em> means not equal)</li>
"You enter {}. Input must not equal Mithridates",
my_name
);
}
</code></pre></pre>
<p>It will display:</p>
<pre><codeclass="language-text">thread 'main' panicked at 'assertion failed: `(left != right)`
left: `"Mithridates"`,
right: `"Mithridates"`: You entered Mithridates. Input must not equal Mithridates', src\main.rs:4:5
</code></pre>
<p>So it is saying "you said that left != right, but left == right". And it displays our message that says <code>You entered Mithridates. Input must not equal Mithridates</code>.</p>
<p><code>unwrap</code> is also good when you are writing your program and you want it to crash when there is a problem. Later, when your code is finished it is good to change <code>unwrap</code> to something else that won't crash.</p>
<p>You can also use <code>expect</code>, which is like <code>unwrap</code> but a bit better because you give it your own message. Textbooks usually give this advice: "If you use <code>.unwrap()</code> a lot, at least use <code>.expect()</code> for better error messages."</p>
let fourth = input.get(3).expect("Input vector needs at least 4 items");
*fourth
}
fn main() {
let my_vec = vec![9, 0, 10];
let fourth = get_fourth(&my_vec);
}
</code></pre></pre>
<p>It crashes again, but the error is better: <code>thread 'main' panicked at 'Input vector needs at least 4 items', src\main.rs:7:18</code>. <code>.expect()</code> is a little better than <code>.unwrap()</code> because of this, but it will still panic on <code>None</code>. Now here is an example of a bad practice, a function that tries to unwrap two times. It takes a <code>Vec<Option<i32>></code>, so maybe each part will have a <code>Some<i32></code> or maybe a <code>None</code>.</p>
println!("Index 0 is: {}", input[0].unwrap());
println!("Index 1 is: {}", input[1].unwrap());
}
fn main() {
let vector = vec![None, Some(1000)]; // This vector has a None, so it will panic
try_two_unwraps(vector);
}
</code></pre></pre>
<p>The message is: <code>thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src\main.rs:2:32</code>. We're not sure if it was the first <code>.unwrap()</code> or the second <code>.unwrap()</code> until we check the line. It would be better to check the length and also to not unwrap. But with <code>.expect()</code> at least it will be a <em>little</em> better. Here it is with <code>.expect()</code>:</p>
println!("Index 0 is: {}", input[0].expect("The first unwrap had a None!"));
println!("Index 1 is: {}", input[1].expect("The second unwrap had a None!"));
}
fn main() {
let vector = vec![None, Some(1000)];
try_two_unwraps(vector);
}
</code></pre></pre>
<p>So that is a bit better: <code>thread 'main' panicked at 'The first unwrap had a None!', src\main.rs:2:32</code>. We have the line number as well so we can find it.</p>
<p>You can also use <code>unwrap_or</code> if you want to always have a value that you want to choose. If you do this it will never panic. That's:</p>
<ul>
<li>
<ol>
<li>good because your program won't panic, but</li>
</ol>
</li>
<li>
<olstart="2">
<li>maybe not good if you want the program to panic if there's a problem.</li>
</ol>
</li>
</ul>
<p>But usually we don't want our program to panic, so <code>unwrap_or</code> is a good method to use.</p>