You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-24 09:46:45 +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:
@ -6,9 +6,8 @@ minutes: 10
|
||||
|
||||
## Blocks
|
||||
|
||||
A block in Rust contains a sequence of expressions.
|
||||
Each block has a value and a type,
|
||||
which are those of the last expression of the block:
|
||||
A block in Rust contains a sequence of expressions. Each block has a value and a
|
||||
type, which are those of the last expression of the block:
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
@ -49,10 +48,15 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
* You can show how the value of the block changes by changing the last line in the block. For instance, adding/removing a semicolon or using a `return`.
|
||||
* Show that a variable's scope is limited by adding a `b` in the inner block in the last example, and then trying to access it outside that block.
|
||||
* Shadowing is different from mutation, because after shadowing both variable's memory locations exist at the same time. Both are available under the same name, depending where you use it in the code.
|
||||
* A shadowing variable can have a different type.
|
||||
* Shadowing looks obscure at first, but is convenient for holding on to values after `.unwrap()`.
|
||||
- You can show how the value of the block changes by changing the last line in
|
||||
the block. For instance, adding/removing a semicolon or using a `return`.
|
||||
- Show that a variable's scope is limited by adding a `b` in the inner block in
|
||||
the last example, and then trying to access it outside that block.
|
||||
- Shadowing is different from mutation, because after shadowing both variable's
|
||||
memory locations exist at the same time. Both are available under the same
|
||||
name, depending where you use it in the code.
|
||||
- A shadowing variable can have a different type.
|
||||
- Shadowing looks obscure at first, but is convenient for holding on to values
|
||||
after `.unwrap()`.
|
||||
|
||||
</details>
|
||||
|
@ -6,10 +6,11 @@ minutes: 5
|
||||
|
||||
If you want to exit any kind of loop early, use
|
||||
[`break`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions).
|
||||
For `loop`, this can take an optional expression that becomes the value of the `loop` expression.
|
||||
For `loop`, this can take an optional expression that becomes the value of the
|
||||
`loop` expression.
|
||||
|
||||
If you want to immediately start
|
||||
the next iteration use [`continue`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions).
|
||||
If you want to immediately start the next iteration use
|
||||
[`continue`](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions).
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
@ -51,9 +52,8 @@ In this case we break the outer loop after 3 iterations of the inner loop.
|
||||
|
||||
<details>
|
||||
|
||||
* Note that `loop` is the only looping construct which returns a non-trivial
|
||||
- Note that `loop` is the only looping construct which returns a non-trivial
|
||||
value. This is because it's guaranteed to be entered at least once (unlike
|
||||
`while` and `for` loops).
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -6,16 +6,16 @@ minutes: 5
|
||||
|
||||
Much of the Rust syntax will be familiar to you from C, C++ or Java:
|
||||
|
||||
* Blocks are delimited by curly braces.
|
||||
* Line comments are started with `//`, block comments are delimited by `/* ...
|
||||
*/`.
|
||||
* Keywords like `if` and `while` work the same.
|
||||
* Variable assignment is done with `=`, comparison is done with `==`.
|
||||
- Blocks are delimited by curly braces.
|
||||
- Line comments are started with `//`, block comments are delimited by
|
||||
`/* ... */`.
|
||||
- Keywords like `if` and `while` work the same.
|
||||
- Variable assignment is done with `=`, comparison is done with `==`.
|
||||
|
||||
## `if` expressions
|
||||
|
||||
You use [`if`
|
||||
expressions](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-expressions)
|
||||
You use
|
||||
[`if` expressions](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-expressions)
|
||||
exactly like `if` statements in other languages:
|
||||
|
||||
```rust,editable
|
||||
@ -34,22 +34,19 @@ fn main() {
|
||||
In addition, you can use `if` as an expression. The last expression of each
|
||||
block becomes the value of the `if` expression:
|
||||
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
let x = 10;
|
||||
let size = if x < 20 {
|
||||
"small"
|
||||
} else {
|
||||
"large"
|
||||
};
|
||||
let size = if x < 20 { "small" } else { "large" };
|
||||
println!("number size: {}", size);
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
Because `if` is an expression and must have a particular type, both of its branch blocks must have the same type. Show what happens if you add `;` after `"small"` in the second example.
|
||||
Because `if` is an expression and must have a particular type, both of its
|
||||
branch blocks must have the same type. Show what happens if you add `;` after
|
||||
`"small"` in the second example.
|
||||
|
||||
When `if` is used in an expression, the expression must have a `;` to separate
|
||||
it from the next statement. Remove the `;` before `println!` to see the compiler
|
||||
|
@ -12,14 +12,15 @@ defined as follows, for an arbitrary n<sub>1</sub> greater than zero:
|
||||
- If _n<sub>i</sub>_ is odd, then _n<sub>i+1</sub> = 3 * n<sub>i</sub> + 1_.
|
||||
|
||||
For example, beginning with _n<sub>1</sub>_ = 3:
|
||||
* 3 is odd, so _n<sub>2</sub>_ = 3 * 3 + 1 = 10;
|
||||
* 10 is even, so _n<sub>3</sub>_ = 10 / 2 = 5;
|
||||
* 5 is odd, so _n<sub>4</sub>_ = 3 * 15 + 1 = 16;
|
||||
* 16 is even, so _n<sub>5</sub>_ = 16 / 2 = 8;
|
||||
* 8 is even, so _n<sub>6</sub>_ = 8 / 2 = 4;
|
||||
* 4 is even, so _n<sub>7</sub>_ = 4 / 2 = 2;
|
||||
* 2 is even, so _n<sub>8</sub>_ = 1; and
|
||||
* the sequence terminates.
|
||||
|
||||
- 3 is odd, so _n<sub>2</sub>_ = 3 * 3 + 1 = 10;
|
||||
- 10 is even, so _n<sub>3</sub>_ = 10 / 2 = 5;
|
||||
- 5 is odd, so _n<sub>4</sub>_ = 3 * 15 + 1 = 16;
|
||||
- 16 is even, so _n<sub>5</sub>_ = 16 / 2 = 8;
|
||||
- 8 is even, so _n<sub>6</sub>_ = 8 / 2 = 4;
|
||||
- 4 is even, so _n<sub>7</sub>_ = 4 / 2 = 2;
|
||||
- 2 is even, so _n<sub>8</sub>_ = 1; and
|
||||
- the sequence terminates.
|
||||
|
||||
Write a function to calculate the length of the collatz sequence for a given
|
||||
initial `n`.
|
||||
|
@ -5,6 +5,7 @@ minutes: 3
|
||||
# Functions
|
||||
|
||||
<!-- mdbook-xgettext: skip -->
|
||||
|
||||
```rust,editable
|
||||
fn gcd(a: u32, b: u32) -> u32 {
|
||||
if b > 0 {
|
||||
@ -21,12 +22,18 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
* Declaration parameters are followed by a type (the reverse of some programming languages), then a return type.
|
||||
* The last expression in a function body (or any block) becomes the return value. Simply omit the `;` at the end of the expression.
|
||||
The `return` keyword can be used for early return, but the "bare value" form is idiomatic at the end of a function (refactor `gcd` to use a `return`).
|
||||
* Some functions have no return value, and return the 'unit type', `()`. The compiler will infer this if the `-> ()` return type is omitted.
|
||||
* Overloading is not supported -- each function has a single implementation.
|
||||
* Always takes a fixed number of parameters. Default arguments are not supported. Macros can be used to support variadic functions.
|
||||
* Always takes a single set of parameter types. These types can be generic, which will be covered later.
|
||||
- Declaration parameters are followed by a type (the reverse of some programming
|
||||
languages), then a return type.
|
||||
- The last expression in a function body (or any block) becomes the return
|
||||
value. Simply omit the `;` at the end of the expression. The `return` keyword
|
||||
can be used for early return, but the "bare value" form is idiomatic at the
|
||||
end of a function (refactor `gcd` to use a `return`).
|
||||
- Some functions have no return value, and return the 'unit type', `()`. The
|
||||
compiler will infer this if the `-> ()` return type is omitted.
|
||||
- Overloading is not supported -- each function has a single implementation.
|
||||
- Always takes a fixed number of parameters. Default arguments are not
|
||||
supported. Macros can be used to support variadic functions.
|
||||
- Always takes a single set of parameter types. These types can be generic,
|
||||
which will be covered later.
|
||||
|
||||
</details>
|
||||
|
@ -8,7 +8,8 @@ There are three looping keywords in Rust: `while`, `loop`, and `for`:
|
||||
|
||||
## `while`
|
||||
|
||||
The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
|
||||
The
|
||||
[`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
|
||||
works much like in other languages, executing the loop body as long as the
|
||||
condition is true.
|
||||
|
||||
@ -55,7 +56,8 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
* We will discuss iteration later; for now, just stick to range expressions.
|
||||
* Note that the `for` loop only iterates to `4`. Show the `1..=5` syntax for an inclusive range.
|
||||
- We will discuss iteration later; for now, just stick to range expressions.
|
||||
- Note that the `for` loop only iterates to `4`. Show the `1..=5` syntax for an
|
||||
inclusive range.
|
||||
|
||||
</details>
|
||||
|
@ -8,11 +8,15 @@ Macros are expanded into Rust code during compilation, and can take a variable
|
||||
number of arguments. They are distinguished by a `!` at the end. The Rust
|
||||
standard library includes an assortment of useful macros.
|
||||
|
||||
* `println!(format, ..)` prints a line to standard output, applying formatting described in [`std::fmt`](https://doc.rust-lang.org/std/fmt/index.html).
|
||||
* `format!(format, ..)` works just like `println!` but returns the result as a string.
|
||||
* `dbg!(expression)` logs the value of the expression and returns it.
|
||||
* `todo!()` marks a bit of code as not-yet-implemented. If executed, it will panic.
|
||||
* `unreachable!()` marks a bit of code as unreachable. If executed, it will panic.
|
||||
- `println!(format, ..)` prints a line to standard output, applying formatting
|
||||
described in [`std::fmt`](https://doc.rust-lang.org/std/fmt/index.html).
|
||||
- `format!(format, ..)` works just like `println!` but returns the result as a
|
||||
string.
|
||||
- `dbg!(expression)` logs the value of the expression and returns it.
|
||||
- `todo!()` marks a bit of code as not-yet-implemented. If executed, it will
|
||||
panic.
|
||||
- `unreachable!()` marks a bit of code as unreachable. If executed, it will
|
||||
panic.
|
||||
|
||||
```rust,editable
|
||||
fn factorial(n: u32) -> u32 {
|
||||
@ -39,7 +43,7 @@ The takeaway from this section is that these common conveniences exist, and how
|
||||
to use them. Why they are defined as macros, and what they expand to, is not
|
||||
especially critical.
|
||||
|
||||
The course does not cover defining macros, but a later section will describe
|
||||
use of derive macros.
|
||||
The course does not cover defining macros, but a later section will describe use
|
||||
of derive macros.
|
||||
|
||||
</details>
|
||||
|
Reference in New Issue
Block a user