Skip to content

Commit 2f9babd

Browse files
authored
Miscellaneous minor improvements (#2370)
1 parent aeb643f commit 2f9babd

File tree

11 files changed

+57
-37
lines changed

11 files changed

+57
-37
lines changed

src/control-flow-basics/break-continue/labels.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,15 @@ fn main() {
1919
print!("elements searched: {elements_searched}");
2020
}
2121
```
22+
23+
<details>
24+
25+
- Labeled break also works on arbitrary blocks, e.g.
26+
```rust
27+
'label: {
28+
break 'label;
29+
println!("This line gets skipped");
30+
}
31+
```
32+
33+
</details>

src/control-flow-basics/exercise.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ initial `n`.
3030
todo!("Implement this")
3131
}
3232
33+
{{#include exercise.rs:tests}}
34+
3335
{{#include exercise.rs:main}}
34-
todo!("Implement this")
35-
}
3636
```

src/control-flow-basics/exercise.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ fn test_collatz_length() {
3434

3535
// ANCHOR: main
3636
fn main() {
37-
// ANCHOR_END: main
3837
println!("Length: {}", collatz_length(11));
3938
}
39+
// ANCHOR_END: main

src/generics/generic-functions.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,25 @@ fn pick<T>(n: i32, even: T, odd: T) -> T {
1919
2020
fn main() {
2121
println!("picked a number: {:?}", pick(97, 222, 333));
22-
println!("picked a tuple: {:?}", pick(28, ("dog", 1), ("cat", 2)));
22+
println!("picked a string: {:?}", pick(28, "dog", "cat"));
2323
}
2424
```
2525

2626
<details>
2727

2828
- Rust infers a type for T based on the types of the arguments and return value.
2929

30+
- In this example we only use the primitive types `i32` and `&str` for `T`, but
31+
we can use any type here, including user-defined types:
32+
33+
```rust,ignore
34+
struct Foo {
35+
val: u8,
36+
}
37+
38+
pick(123, Foo { val: 7 }, Foo { val: 456 });
39+
```
40+
3041
- This is similar to C++ templates, but Rust partially compiles the generic
3142
function immediately, so that function must be valid for all types matching
3243
the constraints. For example, try modifying `pick` to return `even + odd` if

src/methods-and-traits/exercise.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,18 @@
1414

1515
// ANCHOR: solution
1616
// ANCHOR: setup
17-
use std::fmt::Display;
18-
1917
pub trait Logger {
2018
/// Log a message at the given verbosity level.
21-
fn log(&self, verbosity: u8, message: impl Display);
19+
fn log(&self, verbosity: u8, message: &str);
2220
}
2321

2422
struct StderrLogger;
2523

2624
impl Logger for StderrLogger {
27-
fn log(&self, verbosity: u8, message: impl Display) {
25+
fn log(&self, verbosity: u8, message: &str) {
2826
eprintln!("verbosity={verbosity}: {message}");
2927
}
3028
}
31-
32-
fn do_things(logger: &impl Logger) {
33-
logger.log(5, "FYI");
34-
logger.log(2, "Uhoh");
35-
}
3629
// ANCHOR_END: setup
3730

3831
/// Only log messages up to the given verbosity level.
@@ -42,7 +35,7 @@ struct VerbosityFilter {
4235
}
4336

4437
impl Logger for VerbosityFilter {
45-
fn log(&self, verbosity: u8, message: impl Display) {
38+
fn log(&self, verbosity: u8, message: &str) {
4639
if verbosity <= self.max_verbosity {
4740
self.inner.log(verbosity, message);
4841
}
@@ -51,7 +44,8 @@ impl Logger for VerbosityFilter {
5144

5245
// ANCHOR: main
5346
fn main() {
54-
let l = VerbosityFilter { max_verbosity: 3, inner: StderrLogger };
55-
do_things(&l);
47+
let logger = VerbosityFilter { max_verbosity: 3, inner: StderrLogger };
48+
logger.log(5, "FYI");
49+
logger.log(2, "Uhoh");
5650
}
5751
// ANCHOR_END: main

src/pattern-matching/destructuring-enums.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,5 @@ arm, `half` is bound to the value inside the `Ok` variant. In the second arm,
4747
matched.
4848
- Demonstrate what happens when the search is inexhaustive. Note the advantage
4949
the Rust compiler provides by confirming when all cases are handled.
50-
- Save the result of `divide_in_two` in the `result` variable and `match` it in
51-
a loop. That won't compile because `msg` is consumed when matched. To fix it,
52-
match `&result` instead of `result`. That will make `msg` a reference so it
53-
won't be consumed. This
54-
["match ergonomics"](https://rust-lang.github.io/rfcs/2005-match-ergonomics.html)
55-
appeared in Rust 2018. If you want to support older Rust, replace `msg` with
56-
`ref msg` in the pattern.
5750

5851
</details>

src/pattern-matching/exercise.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ fn eval(e: Expression) -> Result<i64, String> {
4444
Expression::Op { op, left, right } => {
4545
let left = match eval(*left) {
4646
Ok(v) => v,
47-
e @ Err(_) => return e,
47+
Err(e) => return Err(e),
4848
};
4949
let right = match eval(*right) {
5050
Ok(v) => v,
51-
e @ Err(_) => return e,
51+
Err(e) => return Err(e),
5252
};
5353
Ok(match op {
5454
Operation::Add => left + right,

src/pattern-matching/match.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,24 @@ Key Points:
5656
- The condition defined in the guard applies to every expression in a pattern
5757
with an `|`.
5858

59+
# More To Explore
60+
61+
- Another piece of pattern syntax you can show students is the `@` syntax which
62+
binds a part of a pattern to a variable. For example:
63+
64+
```rust
65+
let opt = Some(123);
66+
match opt {
67+
outer @ Some(inner) => {
68+
println!("outer: {outer:?}, inner: {inner}");
69+
}
70+
None => {}
71+
}
72+
```
73+
74+
In this example `inner` has the value 123 which it pulled from the `Option`
75+
via destructuring, `outer` captures the entire `Some(inner)` expression, so it
76+
contains the full `Option::Some(123)`. This is rarely used but can be useful
77+
in more complex patterns.
78+
5979
</details>

src/references/shared.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ fn x_axis(x: &i32) -> &(i32, i32) {
3838

3939
<details>
4040

41+
- References can never be null in Rust, so null checking is not necessary.
42+
4143
- A reference is said to "borrow" the value it refers to, and this is a good
4244
model for students not familiar with pointers: code can use the reference to
4345
access the value, but is still "owned" by the original variable. The course

src/references/slices.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ fn main() {
2020
```
2121

2222
- Slices borrow data from the sliced type.
23-
- Question: What happens if you modify `a[3]` right before printing `s`?
2423

2524
<details>
2625

@@ -43,10 +42,4 @@ fn main() {
4342
- Slices always borrow from another object. In this example, `a` has to remain
4443
'alive' (in scope) for at least as long as our slice.
4544

46-
- The question about modifying `a[3]` can spark an interesting discussion, but
47-
the answer is that for memory safety reasons you cannot do it through `a` at
48-
this point in the execution, but you can read the data from both `a` and `s`
49-
safely. It works before you created the slice, and again after the `println`,
50-
when the slice is no longer used.
51-
5245
</details>

src/std-types/hashmap.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ fn main() {
6767
6868
- Alternatively HashMap can be built from any `Iterator` which yields key-value
6969
tuples.
70-
- We are showing `HashMap<String, i32>`, and avoid using `&str` as key to make
71-
examples easier. Using references in collections can, of course, be done, but
72-
it can lead into complications with the borrow checker.
73-
- Try removing `to_string()` from the example above and see if it still
74-
compiles. Where do you think we might run into issues?
7570
7671
- This type has several "method-specific" return types, such as
7772
`std::collections::hash_map::Keys`. These types often appear in searches of

0 commit comments

Comments
 (0)