first exercises
This commit is contained in:
parent
452417beaa
commit
6473f90590
1
subject_source/src/errors.rs
Normal file
1
subject_source/src/errors.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod option;
|
||||
20
subject_source/src/errors/option.rs
Normal file
20
subject_source/src/errors/option.rs
Normal file
@ -0,0 +1,20 @@
|
||||
pub fn is_some(opt: &Option<i32>) -> bool {
|
||||
match opt {
|
||||
None => false,
|
||||
Some(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_default(opt: Option<i32>, default: i32) -> i32 {
|
||||
match opt {
|
||||
None => default,
|
||||
Some(v) => v,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_panic(opt: Option<i32>) -> i32 {
|
||||
match opt {
|
||||
None => panic!("try to get value of a None"),
|
||||
Some(v) => v,
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
pub mod errors;
|
||||
25
subject_source/tests/option.rs
Normal file
25
subject_source/tests/option.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use subject_source::errors::option as opt;
|
||||
|
||||
#[test]
|
||||
pub fn is_some() {
|
||||
assert!(!opt::is_some(&None));
|
||||
assert!(opt::is_some(&Some(0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_or_default() {
|
||||
assert_eq!(opt::get_or_default(None, 1), 1);
|
||||
assert_eq!(opt::get_or_default(Some(1), 1), 1);
|
||||
assert_eq!(opt::get_or_default(Some(2), 1), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
pub fn get_or_panic_none() {
|
||||
let _ = std::hint::black_box(opt::get_or_panic(None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn get_or_panic_some() {
|
||||
assert_eq!(opt::get_or_panic(Some(1)), 1);
|
||||
}
|
||||
57
subject_text/errors/options.md
Normal file
57
subject_text/errors/options.md
Normal file
@ -0,0 +1,57 @@
|
||||
---
|
||||
name = "Options"
|
||||
difficulty = 1
|
||||
exercises = [matching]
|
||||
---
|
||||
|
||||
Sometimes, a function can fail to compute a value simply because the value you asked simply does not exist. For example, when you try to access a collection at a wrong index, or when you want to divide by zero.
|
||||
|
||||
To check for the existence or absence of value, we use the `Option` type. `Option` by itself is not a type, but a generic type, meaning it needs to be annotated with an other type, like this: `Option<Type>`. This allow us to have `Option<i32>`, `Option<String>`, `Option<&str>` ... And even `Option<Option<i32>>` if you want (but this one is a bit weird and you won't encounter it often.
|
||||
|
||||
`Option` comes in two flavors (named variants):
|
||||
|
||||
- `None`, to encode the absence of value.
|
||||
- `Some(v)`, to encode the presence of value. Note the `v` after `Some` to name the wrapped value.
|
||||
|
||||
In order to create values of type `Option<T>`, we just name the variant we want, and if needed, we give the variant a value:
|
||||
|
||||
```example
|
||||
let some_one = Some(1);
|
||||
let nothing: Option<i32> = None;
|
||||
```
|
||||
|
||||
To match against an `Option` value, you can use pattern matching:
|
||||
|
||||
```example
|
||||
let array = [1, 2, 3];
|
||||
let element: Option<&i32> = array.first();
|
||||
|
||||
match element {
|
||||
None => println!("array has no first value"),
|
||||
Some(v) => println!("the first value is {}", v),
|
||||
}
|
||||
```
|
||||
|
||||
In this part we will try to implement usual functions of `Option`:
|
||||
|
||||
*src/errors/option.rs*
|
||||
|
||||
```prototype
|
||||
/// Returns `true` if `opt` is `Some`
|
||||
/// and `false` otherwise.
|
||||
pub fn is_some(opt: &Option<i32>) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the value wrapped in `opt` if it is `Some`,
|
||||
/// and `default` otherwise.
|
||||
pub fn get_or_default(opt: Option<i32>, default: i32) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the value wrapped in `opt` if there is any,
|
||||
/// and panic!() otherwise.
|
||||
pub fn get_or_panic(opt: Option<i32>) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
```
|
||||
18
subject_text/index.md
Normal file
18
subject_text/index.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
revision = 0.1.0
|
||||
parts = [errors]
|
||||
---
|
||||
|
||||
When it comes to programming, it's all fun and games until the real world comes in and sends weird unexpected inputs to your little protege. So you better handle those cases as best as you can. There are 3 main ways of handling errors.
|
||||
|
||||
- Returning some value (usualy an integer) alongside the data to notify there was an error (C, Go)
|
||||
- Throwing exceptions, effectively hijacking the program's control-flow (C++, Java, C#, Python...)
|
||||
- Encode good and bad paths in the type
|
||||
|
||||
The first approach is obviously a thing of the past considering how evolved compilers have become and the need of safety in our apps. You want to give humans as little responsibility as possible when it comes to error checking.
|
||||
|
||||
The second approach is more common in mainstream languages, and the third in functional languages, more precisely languages with so called ["Algebraic Data Types"](https://en.wikipedia.org/wiki/Algebraic_data_type) (aka ["tagged unions"](https://en.wikipedia.org/wiki/Tagged_union)). The second approach is usualy less verbose because it handles error propagation for you, but this approach has many downsides that make languages slowly adopt the third approach ([C++](https://en.cppreference.com/w/cpp/utility/optional), [Python](https://docs.python.org/3/library/typing.html#typing.Optional)), mainly because of control-flow.
|
||||
|
||||
Rust took the third approach, as it is simple to reason about for the compiler and of course makes it easy to prove the soundness of you program. It even helps modeling your application such that ["no invalid state can be represented"](https://geeklaunch.io/blog/make-invalid-states-unrepresentable/) but it's a topic we won't cover in this course.
|
||||
|
||||
This training session will cover the two main types of error (`Option` and `Result`) in Rust, and use them in the context of collections and strings.
|
||||
Loading…
x
Reference in New Issue
Block a user