1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-06-17 14:47:35 +02:00

Format all Markdown files with dprint (#1157)

This is the result of running `dprint fmt` after removing `src/` from
the list of excluded directories.

This also reformats the Rust code: we might want to tweak this a bit in
the future since some of the changes removes the hand-formatting. Of
course, this formatting can be seen as a mis-feature, so maybe this is
good overall.

Thanks to mdbook-i18n-helpers 0.2, the POT file is nearly unchanged
after this, meaning that all existing translations remain valid! A few
messages were changed because of stray whitespace characters:

     msgid ""
     "Slices always borrow from another object. In this example, `a` has to remain "
    -"'alive' (in scope) for at least as long as our slice. "
    +"'alive' (in scope) for at least as long as our slice."
     msgstr ""

The formatting is enforced in CI and we will have to see how annoying
this is in practice for the many contributors. If it becomes annoying,
we should look into fixing dprint/check#11 so that `dprint` can annotate
the lines that need fixing directly, then I think we can consider more
strict formatting checks.

I added more customization to `rustfmt.toml`. This is to better emulate
the dense style used in the course:

- `max_width = 85` allows lines to take up the full width available in
our code blocks (when taking margins and the line numbers into account).
- `wrap_comments = true` ensures that we don't show very long comments
in the code examples. I edited some comments to shorten them and avoid
unnecessary line breaks — please trim other unnecessarily long comments
when you see them! Remember we're writing code for slides 😄
- `use_small_heuristics = "Max"` allows for things like struct literals
and if-statements to take up the full line width configured above.

The formatting settings apply to all our Rust code right now — I think
we could improve this with https://github.com/dprint/dprint/issues/711
which lets us add per-directory `dprint` configuration files. However,
the `inherit: true` setting is not yet implemented (as far as I can
tell), so a nested configuration file will have to copy most or all of
the top-level file.
This commit is contained in:
Martin Geisler
2023-12-31 00:15:07 +01:00
committed by GitHub
parent f43e72e0ad
commit c9f66fd425
302 changed files with 3067 additions and 2622 deletions

View File

@ -7,4 +7,3 @@ publish = false
[[bin]]
name = "transpose"
path = "exercise.rs"

View File

@ -36,9 +36,10 @@ fn describe_point(point: (i32, i32)) {
<details>
* Create a new array pattern using `_` to represent an element.
* Add more values to the array.
* Point out that how `..` will expand to account for different number of elements.
* Show matching against the tail with patterns `[.., b]` and `[a@..,b]`
- Create a new array pattern using `_` to represent an element.
- Add more values to the array.
- Point out that how `..` will expand to account for different number of
elements.
- Show matching against the tail with patterns `[.., b]` and `[a@..,b]`
</details>

View File

@ -16,6 +16,7 @@ Use an array such as the above to write a function `transpose` which will
transpose a matrix (turn rows into columns):
<!-- mdbook-xgettext: skip -->
```bob
⎛⎡1 2 3⎤⎞ ⎡1 4 7⎤
"transpose"⎜⎢4 5 6⎥⎟ "=="⎢2 5 8⎥

View File

@ -11,18 +11,19 @@ fn main() {
let primes = [2, 3, 5, 7, 11, 13, 17, 19];
for prime in primes {
for i in 2..prime {
assert_ne!(prime % i, 0);
}
}
assert_ne!(prime % i, 0);
}
}
}
```
<details>
This functionality uses the `IntoIterator` trait, but we haven't covered that yet.
This functionality uses the `IntoIterator` trait, but we haven't covered that
yet.
The `assert_ne!` macro is new here. There are also `assert_eq!` and `assert!`
macros. These are always checked while, debug-only variants like
`debug_assert!` compile to nothing in release builds.
macros. These are always checked while, debug-only variants like `debug_assert!`
compile to nothing in release builds.
</details>

View File

@ -10,6 +10,7 @@ comparisons are done from top to bottom and the first match wins.
The patterns can be simple values, similarly to `switch` in C and C++:
```rust,editable
#[rustfmt::skip]
fn main() {
let input = 'x';
match input {
@ -23,28 +24,36 @@ fn main() {
```
The `_` pattern is a wildcard pattern which matches any value. The expressions
_must_ be irrefutable, meaning that it covers every possibility, so `_` is
often used as the final catch-all case.
_must_ be irrefutable, meaning that it covers every possibility, so `_` is often
used as the final catch-all case.
Match can be used as an expression. Just like `if`, each match arm must have the same type. The type is the last
expression of the block, if any. In the example above, the type is `()`.
Match can be used as an expression. Just like `if`, each match arm must have the
same type. The type is the last expression of the block, if any. In the example
above, the type is `()`.
A variable in the pattern (`key` in this example) will create a binding that
can be used within the match arm.
A variable in the pattern (`key` in this example) will create a binding that can
be used within the match arm.
A match guard causes the arm to match only if the condition is true.
<details>
Key Points:
* You might point out how some specific characters are being used when in a pattern
* `|` as an `or`
* `..` can expand as much as it needs to be
* `1..=5` represents an inclusive range
* `_` is a wild card
* Match guards as a separate syntax feature are important and necessary when we wish to concisely express more complex ideas than patterns alone would allow.
* They are not the same as separate `if` expression inside of the match arm. An `if` expression inside of the branch block (after `=>`) happens after the match arm is selected. Failing the `if` condition inside of that block won't result in other arms
of the original `match` expression being considered.
* The condition defined in the guard applies to every expression in a pattern with an `|`.
- You might point out how some specific characters are being used when in a
pattern
- `|` as an `or`
- `..` can expand as much as it needs to be
- `1..=5` represents an inclusive range
- `_` is a wild card
- Match guards as a separate syntax feature are important and necessary when we
wish to concisely express more complex ideas than patterns alone would allow.
- They are not the same as separate `if` expression inside of the match arm. An
`if` expression inside of the branch block (after `=>`) happens after the
match arm is selected. Failing the `if` condition inside of that block won't
result in other arms of the original `match` expression being considered.
- The condition defined in the guard applies to every expression in a pattern
with an `|`.
</details>

View File

@ -5,17 +5,18 @@ minutes: 10
# Tuples and Arrays
Tuples and arrays are the first "compound" types we have seen. All elements of
an array have the same type, while tuples can accommodate different types.
Both types have a size fixed at compile time.
an array have the same type, while tuples can accommodate different types. Both
types have a size fixed at compile time.
| | Types | Literals |
|--------|-------------------------------|-----------------------------------|
| ------ | ----------------------------- | --------------------------------- |
| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |
| Tuples | `()`, `(T,)`, `(T1, T2)`, ... | `()`, `('x',)`, `('x', 1.2)`, ... |
Array assignment and access:
<!-- mdbook-xgettext: skip -->
```rust,editable
fn main() {
let mut a: [i8; 10] = [42; 10];
@ -27,6 +28,7 @@ fn main() {
Tuple assignment and access:
<!-- mdbook-xgettext: skip -->
```rust,editable
fn main() {
let t: (i8, bool) = (7, true);
@ -41,37 +43,40 @@ Key points:
Arrays:
* A value of the array type `[T; N]` holds `N` (a compile-time constant) elements of the same type `T`.
Note that the length of the array is *part of its type*, which means that `[u8; 3]` and
`[u8; 4]` are considered two different types. Slices, which have a size determined at runtime,
are covered later.
- A value of the array type `[T; N]` holds `N` (a compile-time constant)
elements of the same type `T`. Note that the length of the array is _part of
its type_, which means that `[u8; 3]` and `[u8; 4]` are considered two
different types. Slices, which have a size determined at runtime, are covered
later.
* Try accessing an out-of-bounds array element. Array accesses are checked at
- Try accessing an out-of-bounds array element. Array accesses are checked at
runtime. Rust can usually optimize these checks away, and they can be avoided
using unsafe Rust.
* We can use literals to assign values to arrays.
- We can use literals to assign values to arrays.
* The `println!` macro asks for the debug implementation with the `?` format
parameter: `{}` gives the default output, `{:?}` gives the debug output. Types such as
integers and strings implement the default output, but arrays only implement the debug output.
This means that we must use debug output here.
- The `println!` macro asks for the debug implementation with the `?` format
parameter: `{}` gives the default output, `{:?}` gives the debug output. Types
such as integers and strings implement the default output, but arrays only
implement the debug output. This means that we must use debug output here.
* Adding `#`, eg `{a:#?}`, invokes a "pretty printing" format, which can be easier to read.
- Adding `#`, eg `{a:#?}`, invokes a "pretty printing" format, which can be
easier to read.
Tuples:
* Like arrays, tuples have a fixed length.
- Like arrays, tuples have a fixed length.
* Tuples group together values of different types into a compound type.
- Tuples group together values of different types into a compound type.
* Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`.
- Fields of a tuple can be accessed by the period and the index of the value,
e.g. `t.0`, `t.1`.
* The empty tuple `()` is also known as the "unit type". It is both a type, and
the only valid value of that type --- that is to say both the type and its value
are expressed as `()`. It is used to indicate, for example, that a function or
expression has no return value, as we'll see in a future slide.
* You can think of it as `void` that can be familiar to you from other
programming languages.
- The empty tuple `()` is also known as the "unit type". It is both a type, and
the only valid value of that type --- that is to say both the type and its
value are expressed as `()`. It is used to indicate, for example, that a
function or expression has no return value, as we'll see in a future slide.
- You can think of it as `void` that can be familiar to you from other
programming languages.
</details>