1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-12-23 06:56:25 +02:00

Comprehensive Rust v2 (#1073)

I've taken some work by @fw-immunant and others on the new organization
of the course and condensed it into a form amenable to a text editor and
some computational analysis. You can see the inputs in `course.py` but
the interesting bits are the output: `outline.md` and `slides.md`.

The idea is to break the course into more, smaller segments with
exercises at the ends and breaks in between. So `outline.md` lists the
segments, their duration, and sums those durations up per-day. It shows
we're about an hour too long right now! There are more details of the
segments in `slides.md`, or you can see mostly the same stuff in
`course.py`.

This now contains all of the content from the v1 course, ensuring both
that we've covered everything and that we'll have somewhere to redirect
every page.

Fixes #1082.
Fixes #1465.

---------

Co-authored-by: Nicole LeGare <dlegare.1001@gmail.com>
Co-authored-by: Martin Geisler <mgeisler@google.com>
This commit is contained in:
Dustin J. Mitchell
2023-11-29 10:39:24 -05:00
committed by GitHub
parent ea204774b6
commit 6d19292f16
309 changed files with 6807 additions and 4281 deletions

View File

@@ -0,0 +1,9 @@
[package]
name = "references"
version = "0.1.0"
edition = "2021"
publish = false
[[bin]]
name = "references"
path = "exercise.rs"

View File

@@ -0,0 +1,34 @@
---
minutes: 10
---
# Exclusive References
Exclusive references, also known as mutable references, allow changing the value
they refer to. They have type `&mut T`.
<!-- mdbook-xgettext: skip -->
```rust,editable
fn main() {
let mut point = (1, 2);
let x_coord = &mut point.0;
*x_coord = 20;
println!("point: {point:?}");
}
```
<details>
Key points:
* "Exclusive" means that only this reference can be used to access the value.
No other references (shared or exclusive) can exist at the same time, and the
referenced value cannot be accessed while the exclusive reference exists. Try
making an `&point.0` or changing `point.0` while `x_coord` is alive.
* Be sure to note the difference between `let mut x_coord: &i32` and `let
x_coord: &mut i32`. The first one represents a shared reference which can be
bound to different values, while the second represents an exclusive reference
to a mutable value.
</details>

View File

@@ -0,0 +1,31 @@
---
minutes: 30
---
# Exercise: Geometry
We will create a few utility functions for 3-dimensional geometry, representing
a point as `[f64;3]`. It is up to you to determine the function signatures.
```rust,compile_fail
// Calculate the magnitude of a vector by summing the squares of its coordinates
// and taking the square root. Use the `sqrt()` method to calculate the square
// root, like `v.sqrt()`.
{{#include exercise.rs:magnitude}}
fn magnitude(...) -> f64 {
todo!()
}
// Normalize a vector by calculating its magnitude and dividing all of its
// coordinates by that magnitude.
{{#include exercise.rs:normalize}}
fn normalize(...) {
todo!()
}
// Use the following `main` to test your work.
{{#include exercise.rs:main}}
```

View File

@@ -0,0 +1,45 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ANCHOR: solution
/// Calculate the magnitude of the given vector.
fn magnitude(vector: &[f64; 3]) -> f64 {
let mut mag_squared = 0.0;
for coord in vector {
mag_squared += coord * coord;
}
mag_squared.sqrt()
}
/// Change the magnitude of the vector to 1.0 without changing its direction.
fn normalize(vector: &mut [f64; 3]) {
let mag = magnitude(vector);
vector[0] /= mag;
vector[1] /= mag;
vector[2] /= mag;
}
// ANCHOR: main
fn main() {
println!(
"Magnitude of a unit vector: {}",
magnitude(&[0.0, 1.0, 0.0])
);
let mut v = [1.0, 2.0, 9.0];
println!("Magnitude of {v:?}: {}", magnitude(&v));
normalize(&mut v);
println!("Magnitude of {v:?} after normalization: {}", magnitude(&v));
}
// ANCHOR_END: main

70
src/references/shared.md Normal file
View File

@@ -0,0 +1,70 @@
---
minutes: 10
---
# Shared References
A reference provides a way to access another value without taking responsibility
for the value, and is also called "borrowing". Shared references are read-only,
and the referenced data cannot change.
<!-- mdbook-xgettext: skip -->
```rust,editable
fn main() {
let a = 'A';
let b = 'B';
let mut r: &char = &a;
println!("r: {}", *r);
r = &b;
println!("r: {}", *r);
}
```
A shared reference to a type `T` has type `&T`. A reference value is made with the `&`
operator. The `*` operator "dereferences" a reference, yielding its value.
Rust will statically forbid dangling references:
<!-- mdbook-xgettext: skip -->
```rust,editable,compile_fail
fn x_axis(x: i32) -> &(i32, i32) {
let point = (x, 0);
return &point;
}
```
<details>
* A reference is said to "borrow" the value it refers to, and this is a good
model for students not familiar with pointers: code can use the reference to
access the value, but is still "owned" by the original variable. The course
will get into more detail on ownership in day 3.
* References are implemented as pointers, and a key advantage is that they can
be much smaller than the thing they point to. Students familiar with C or C++
will recognize references as pointers. Later parts of the course will cover
how Rust prevents the memory-safety bugs that come from using raw pointers.
* Rust does not automatically create references for you - the `&` is always
required.
* Rust will auto-dereference in some cases, in particular when invoking
methods (try `r.count_ones()`). There is no need for an `->` operator
like in C++.
* In this example, `r` is mutable so that it can be reassigned (`r = &b`).
Note that this re-binds `r`, so that it refers to something else. This is
different from C++, where assignment to a reference changes the referenced
value.
* A shared reference does not allow modifying the value it refers to, even if
that value was mutable. Try `*r = 'X'`.
* Rust is tracking the lifetimes of all references to ensure they live long
enough. Dangling references cannot occur in safe Rust. `x_axis` would return
a reference to `point`, but `point` will be deallocated when the function
returns, so this will not compile.
* We will talk more about borrowing when we get to ownership.
</details>

View File

@@ -0,0 +1,5 @@
# Solution
```rust,editable
{{#include exercise.rs:solution}}
```