Merge branch 'vec-part' into fix-result-part

This commit is contained in:
lilymonade 2025-03-11 22:46:42 +01:00
commit 9f347a264f
Signed by: lilymonade
GPG Key ID: F8967EC454DBDCB6
9 changed files with 70 additions and 3 deletions

View File

@ -37,3 +37,10 @@ exercises:
- "get_val_or_panic_ok"
- "discard_err_ok"
- "discard_err_err"
access:
required_files:
- "src/vec.rs"
- "src/vec/access.rs"
tests:
- "add_last_two_not_enough"
- "add_last_two_enough"

View File

@ -1 +1,2 @@
pub mod errors;
pub mod vec;

View File

@ -0,0 +1 @@
pub mod access;

View File

@ -0,0 +1,10 @@
/// Add the last two numbers of the input slice.
///
/// If the slice is not large enough, return `None`
/// If it is, return the computed value in a `Some`
pub fn add_last_two(v: &[f32]) -> Option<f32> {
match v.last_chunk() {
Some([a, b]) => Some(a + b),
None => None,
}
}

View File

@ -0,0 +1,11 @@
use subject_source::vec::access;
#[test]
pub fn add_last_two_not_enough() {
assert_eq!(access::add_last_two(&[1.0]), None);
}
#[test]
pub fn add_last_two_enough() {
assert_eq!(access::add_last_two(&[1.0, 2.0, 3.0]), Some(5.0));
}

View File

@ -6,7 +6,7 @@ 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).
- 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/).

View File

@ -1,6 +1,6 @@
---
revision = "0.1.0"
parts = ["errors"]
revision = "0.3.0"
parts = ["errors", "vec"]
---
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.

View File

@ -5,4 +5,7 @@
   │   ├── option.rs
   │   └── result.rs
   ├── errors.rs
   ├── vec
   │   └── access.rs
   ├── vec.rs
   └── lib.rs

34
subject_text/vec/index.md Normal file
View File

@ -0,0 +1,34 @@
---
name = "Vecs and slices"
difficulty = 2
exercises = ["access.md"]
---
Let's now look at some functions on [`slice`](https://doc.rust-lang.org/std/primitive.slice.html)s and [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html)s. Instead of manualy checking things we will follow the type system using `Option`s and `Result`s we saw earlier.
```note
Slices (`[T]`) represent some memory space containing an arbitrary number of elements of type `T`. Since they don't have a size known at compilation time, we can only access them through pointers, commonly `&[T]` (references to slices).
```
```deepening
`Vec<T>` can be seen as [owned](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html) `[T]`, it means that every function working on a `&[T]` can work on a `&Vec<T>`.
```
```prototype
/// Add the last two numbers of the input slice.
///
/// If the slice is not large enough, return `None`
/// If it is, return the computed value in a `Some`
pub fn add_last_two(v: &[f32]) -> Option<f32> {
unimplemented!()
}
```
```example
fn main() {
assert_eq!(add_last_two(&[]), None);
assert_eq!(add_last_two(&[10.0]), None);
assert_eq!(add_last_two(&[1.0, 2.0, 3.0]), Some(5.0));
}
```