Error Handling Flashcards

1
Q

What are two important types in rust, used for error handling? What are their possible variants?

A

Result (OK, Err) and Option (Some, None)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q
What is equivalent to:
let first_inner = match first {
  Ok(inner) => inner,
  Err(_) => Person {name: "unknown",},
}
A
let first_inner = first.unwrap_or_default();
*default value should be defined
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q
What is equivalent to:
let first_inner = match first {
  Ok(inner) => inner,
  Err(_) => panic!("awh!!!"),
};
A

let first_inner = first.expect(“awh!!!”);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
What is equivalent to:
let first_inner = first.unwrap_or_default();
*first is of type Result
*Person is struct with one field named "name" and its default value is "unknown"
A
let first_inner = match first {
  Ok(inner) => inner,
  Err(_) => Person {name: "unknown",},
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q
What is equivalent to:
let first_inner = first.expect("awh!!!");
A

let first_inner = match first {
Ok(inner) => inner,
Err(_) => panic!(“awh!!!”),
};

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
What is equivalent to:
let record = save_to_database(text)?;
*Assuming save_to_database() returns Result type
A
let record = match save_to_database(text) {
  Ok(value) => value,
  Err(e) => return Err(e),
};
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q
What is equivalent to:
let record = match save_to_database(text) {
  Ok(value) => value,
  Err(e) => return Err(e),
};
A

let record = save_to_database(text)?;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q
Use old macro to get:
let record = save_to_database(text)?;
A

let record = try!(save_to_database(text));

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Where can we use the ‘?’ operator?

A

In the past, only for functions that returns Result type
In rust 1.22.0+, for function that returns Option type (excluding main and test functions)
In rust 1.26.0+, for main function that returns Result type.
In rust 1.28.0+, for test functions that returns Result type.
*In general for any type that implements std::ops::Try.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What is equivalent to:
let num = n.last()?;
Some(num + 5)

*Assuming n is of type &[i32]

A
let num = match n.last() {
  Some(num) => Some(num + 5),
  None => None,
};
***(I think it should be return None - need to make sure!!!)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What is equivalent to:

let num: i32 = “10”.parse().expect(“parsing failed”);

A
let num: i32 = match "10".parse() {
  Ok(inner) => inner,
  Err(_) => panic!("parsing failed"),
};
*** is the panic! statement should be inside of { } and end with semicolon? like so:
Err(_) => {panic!("parsing failed");}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Name two solutions to the problem of a function that might fail in multiple ways.

A

Solution 1: Returning a Box trait object

Solution 2: Defining a custom error type

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What traits are needed to define a custom error type? What trait is need to be able to use the ? operator.

A

Error trait is needed to use custom error.

From trait is needed to use the ? operator.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What is the main downside of using Box strategy for handling multiple error types?
What should we use in order to overcome this issue?

A

Given a Box, one can’t inspect the error type in code, hence can’t handle different errors based on their type.
To over come the issue - use custom error type.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

When is it ok to use ? operator in the following code
fn create_doc(name: &str) ->Result {
let file =
OpenOptions::new().write(true).create_new(true).open(name)?;
}

A
The From trait must be implemented:
impl From for MyError {
  fn from(other: io::Error) -> Self {
    MyError::something(other)
  }
}
...
Enum MyError { something(io::Error), ...}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

How can you shorten the generic type:

Result;

A

pub type Result = Result;

and you can right simply Result

17
Q

How to enable backtrace capturing in rust?

A

running:

RUST_BACKTRACE=1 cargo run

18
Q

Name three crates that are designated for error handling. Do they support: Display implementation, From conversions, Backtraces? What kind of Macro?

A
  1. quick-error (regular Macro, supports all except Backtraces)
  2. error-chain (regular Macro, supports all)
  3. failure (derive Macro supports all)
19
Q

How do you test which variant of Result you have?

A

Using the methods: is_ok, is_err

20
Q

How do you test which variant of Option you have?

A

Using the methods: is_some, is_none

21
Q
Why is the following is an antipattern?
if option_value.is_some() {
  let inner = option_value.unwrap();
  println!("inner = {}", inner)
}
What is a better way to do it?
A
  1. The code indeed ensures that the unwrap() won’t panic, but it isn’t very clear.
  2. The code is also doing a redundant check of which variant the value is.

A better, more idiomatic option, will be:
if let Some(inner) = option_value {
println!(“inner = {}”, inner)
}

22
Q

How can you convert a Result into an Option?

A

By using the ok method:
Ok(T).ok() converts to Some(T)
Err(E).ok() converts to None and discards the error value

23
Q

How can you convert an Option into a Result?

A

By using the ok_or method.
Some(T).ok_or(err_value) converts to Ok(T)
None.ok_or(err_value) converts to Err(err_value)
*notice that we need to specify the error value.

24
Q

How can you specify and use fallback (specific one) values for Option and Result types?

A
By using the unwrap_or method. 
For Result:
  Ok(T).unwrap_or(fallback) -> T
  Err(T).unwrap_or(fallback) -> fallback
For Option:
  Some(T).unwrap_or(fallback) -> T
  None.unwrap_or(fallback) -> fallback
25
Q

What is a better way to write:
let first_inner = match first {
Ok(inner) => inner,
Err(_) => Person {name: String::from(“unknown”)},
};
*assume there is no implementation of Default for Person

A
use unwrap_or like so:
let first_inner = first.unwrap_or(
  Person {name: String::from("unknown")});
26
Q
Use unwrap_or_default to write the following:
let first_inner = match first {
  Ok(inner) => inner,
  Err(_) => Person {name: String::from("unknown")},
};
A
impl Default for Person {
  fn default() -> Self {
    Person {name: String::from("unknown"),}
  }
}
let first_inner = first.unwrap_or_default()
27
Q
What is a better way to write:
let new_var = match var {
  Ok(inner) => inner.operation(),
  Err(e) => Err(e),
};
and:
let new_var = match var {
  Some(inner) => inner.operation(),
  None => None,
};
A
use map method.
let new_var = var.map(|v| v.operation())
28
Q
  1. What happens by default, when a Rust program panics?
  2. What is the alternative, more simple and dirty way?
  3. How to switch to the alternative?
A
  1. By default, when a panic occurs, the program starts unwinding, which means Rust walks back up the stack and cleans up the data from each function it encounters.
  2. The alternative is to immediately abort, which ends the program without cleaning up. Memory that the program was using will then need to be cleaned up by the operating system. This will also result in a smaller binary.
  3. you can switch from unwinding to aborting upon a panic by adding panic = ‘abort’ to the appropriate [profile] sections in your Cargo.toml file. For example, if you want to abort on panic in release mode, add this:

[profile.release]
panic = ‘abort’

29
Q

Write a code that do the following.

Get a file handle of a file named “hello.txt”. Create one if it does not exist. Panic if any other error occurs.

A

use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let f = File::open("hello.txt").unwrap_or_else(|error| {
        if error.kind() == ErrorKind::NotFound {
            File::create("hello.txt").unwrap_or_else(|error| {
                panic!("Problem creating the file: {:?}", error);
            })
        } else {
            panic!("Problem opening the file: {:?}", error);
        }
    });
}