parent
75d99a912a
commit
1787c39be0
@ -22,3 +22,18 @@ exercises:
|
||||
- "get_or_default_some_diff"
|
||||
- "get_or_panic_none"
|
||||
- "get_or_panic_some"
|
||||
result:
|
||||
required_files:
|
||||
- "src/errors.rs"
|
||||
- "src/errors/option.rs"
|
||||
tests:
|
||||
- "is_err_err"
|
||||
- "is_ok_err"
|
||||
- "is_err_ok"
|
||||
- "is_ok_ok"
|
||||
- "get_err_or_panic_err"
|
||||
- "get_err_or_panic_ok"
|
||||
- "get_val_or_panic_err"
|
||||
- "get_val_or_panic_ok"
|
||||
- "discard_err_ok"
|
||||
- "discard_err_err"
|
||||
|
||||
@ -1 +1,2 @@
|
||||
pub mod option;
|
||||
pub mod result;
|
||||
|
||||
37
subject_source/src/errors/result.rs
Normal file
37
subject_source/src/errors/result.rs
Normal file
@ -0,0 +1,37 @@
|
||||
/// Returns `true` if the result contains an `Err`
|
||||
pub fn is_err(res: &Result<i32, &str>) -> bool {
|
||||
match res {
|
||||
Err(_) => true,
|
||||
Ok(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the result contains a `Ok`
|
||||
pub fn is_ok(res: &Result<i32, &str>) -> bool {
|
||||
!is_err(res)
|
||||
}
|
||||
|
||||
/// Returns the wrapped `&str` if any, panic otherwise
|
||||
pub fn get_err_or_panic(res: Result<i32, &str>) -> &str {
|
||||
match res {
|
||||
Err(e) => e,
|
||||
Ok(_) => panic!("result was not an error"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the wrapped `i32` if any, panic otherwise
|
||||
pub fn get_val_or_panic(res: Result<i32, &str>) -> i32 {
|
||||
match res {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("result was an error"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms `Ok` to `Some` and `Err` to `None`
|
||||
/// effectively discarding the `Err` wrapped value
|
||||
pub fn discard_err(res: Result<i32, &str>) -> Option<i32> {
|
||||
match res {
|
||||
Ok(v) => Some(v),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
53
subject_source/tests/result.rs
Normal file
53
subject_source/tests/result.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use subject_source::errors::result;
|
||||
|
||||
#[test]
|
||||
pub fn is_err_err() {
|
||||
assert!(result::is_err(&Err("oh no")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn is_err_ok() {
|
||||
assert!(!result::is_err(&Ok(420)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn is_ok_err() {
|
||||
assert!(!result::is_ok(&Err("oh no")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn is_ok_ok() {
|
||||
assert!(result::is_ok(&Ok(420)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_err_or_panic_err() {
|
||||
assert_eq!(result::get_err_or_panic(Err("ayaya")), "ayaya");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
pub fn get_err_or_panic_ok() {
|
||||
let _ = std::hint::black_box(result::get_err_or_panic(Ok(10)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_val_or_panic_ok() {
|
||||
assert_eq!(result::get_val_or_panic(Ok(10)), 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
pub fn get_val_or_panic_err() {
|
||||
let _ = std::hint::black_box(result::get_val_or_panic(Err("oaizjd")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn discard_err_err() {
|
||||
assert_eq!(result::discard_err(Err("hello")), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn discard_err_ok() {
|
||||
assert_eq!(result::discard_err(Ok(128)), Some(128));
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
name = "Errors"
|
||||
difficulty = 1
|
||||
exercises = ["option.md"]
|
||||
exercises = ["option.md", "result.md"]
|
||||
---
|
||||
|
||||
|
||||
64
subject_text/errors/result.md
Normal file
64
subject_text/errors/result.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
name = "Results"
|
||||
file = "src/errors/result.rs"
|
||||
---
|
||||
|
||||
We saw earlier the `Option` type, which represents a possibly absent value (sometimes called "nullable" in other languages). Now it would be useful to carry **the reason** of this absence of value. Let's say you are parsing an integer from a `String`, there are multiple ways it can fail.
|
||||
|
||||
- The string contains invalid characters (non-digits).
|
||||
- The value we want to parse is too large (for example, trying to parse `"999999999999"` as an i32).
|
||||
|
||||
If we want to react properly, we need to know why it failed. So instead of having only `None` as output, we would like a variant like `SomeError(v)`. In Rust, this type with `Some` and `SomeError` variants is called [`Result`](https://doc.rust-lang.org/std/result/).
|
||||
|
||||
Its variants are `Ok` and `Err`, and we can use it much like `Option`:
|
||||
|
||||
```rust
|
||||
// creating values of type Result
|
||||
let itworked: Result<i32, &str> = Ok(420);
|
||||
let oops: Result<i32, &str> = Err("badb002e");
|
||||
|
||||
// using values from Result
|
||||
match itworked {
|
||||
Ok(value) => println!("yes, we got {value}"),
|
||||
Err(err) => eprintln!("oh no, some error occured: {err}"),
|
||||
}
|
||||
```
|
||||
|
||||
```prototype
|
||||
/// Returns `true` if the result contains an `Err`
|
||||
pub fn is_err(res: &Result<i32, &str>) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns `true` if the result contains a `Ok`
|
||||
pub fn is_ok(res: &Result<i32, &str>) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the wrapped `&str` if any, panic otherwise
|
||||
pub fn get_err_or_panic(res: Result<i32, &str>) -> &str {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the wrapped `i32` if any, panic otherwise
|
||||
pub fn get_val_or_panic(res: Result<i32, &str>) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Transforms `Ok` to `Some` and `Err` to `None`
|
||||
/// effectively discarding the `Err` wrapped value
|
||||
pub fn discard_err(res: Result<i32, &str>) -> Option<i32> {
|
||||
unimplemented!()
|
||||
}
|
||||
```
|
||||
|
||||
```example
|
||||
fn main() {
|
||||
dbg!(is_err(Ok(10))); // false
|
||||
dbg!(is_ok(Ok(128))); // true
|
||||
dbg!(get_err_or_panic(Err("oh no"))); // "oh no"
|
||||
dbg!(get_val_or_panic(Ok(420))); // 420
|
||||
dbg!(discard_err(Ok(69))); // Some(69)
|
||||
}
|
||||
```
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user