1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-04-26 09:12:58 +02:00

Indent code in speaker notes (#476)

* Indent code in speaker notes

#475

* Update stack.md

* Update destructuring-arrays.md

* Update hashmap.md

* Update traits.md
This commit is contained in:
Charisee Chiw 2023-03-11 14:12:32 -08:00 committed by GitHub
parent 368f3ba302
commit 59d3d7f625
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 122 deletions

View File

@ -65,91 +65,91 @@ Key Points:
types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees
that `size_of::<T>()` equals `size_of::<Option<T>>()`. that `size_of::<T>()` equals `size_of::<Option<T>>()`.
Example code if you want to show how the bitwise representation *may* look like in practice. Example code if you want to show how the bitwise representation *may* look like in practice.
It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe. It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe.
```rust,editable ```rust,editable
use std::mem::transmute; use std::mem::transmute;
macro_rules! dbg_bits { macro_rules! dbg_bits {
($e:expr, $bit_type:ty) => { ($e:expr, $bit_type:ty) => {
println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e));
}; };
} }
fn main() { fn main() {
// TOTALLY UNSAFE. Rust provides no guarantees about the bitwise // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise
// representation of types. // representation of types.
unsafe { unsafe {
println!("Bitwise representation of bool"); println!("Bitwise representation of bool");
dbg_bits!(false, u8); dbg_bits!(false, u8);
dbg_bits!(true, u8); dbg_bits!(true, u8);
println!("Bitwise representation of Option<bool>"); println!("Bitwise representation of Option<bool>");
dbg_bits!(None::<bool>, u8); dbg_bits!(None::<bool>, u8);
dbg_bits!(Some(false), u8); dbg_bits!(Some(false), u8);
dbg_bits!(Some(true), u8); dbg_bits!(Some(true), u8);
println!("Bitwise representation of Option<Option<bool>>"); println!("Bitwise representation of Option<Option<bool>>");
dbg_bits!(Some(Some(false)), u8); dbg_bits!(Some(Some(false)), u8);
dbg_bits!(Some(Some(true)), u8); dbg_bits!(Some(Some(true)), u8);
dbg_bits!(Some(None::<bool>), u8); dbg_bits!(Some(None::<bool>), u8);
dbg_bits!(None::<Option<bool>>, u8); dbg_bits!(None::<Option<bool>>, u8);
println!("Bitwise representation of Option<&i32>"); println!("Bitwise representation of Option<&i32>");
dbg_bits!(None::<&i32>, usize); dbg_bits!(None::<&i32>, usize);
dbg_bits!(Some(&0i32), usize); dbg_bits!(Some(&0i32), usize);
} }
} }
``` ```
More complex example if you want to discuss what happens when we chain more than 256 `Option`s together. More complex example if you want to discuss what happens when we chain more than 256 `Option`s together.
```rust,editable ```rust,editable
#![recursion_limit = "1000"] #![recursion_limit = "1000"]
use std::mem::transmute; use std::mem::transmute;
macro_rules! dbg_bits {
($e:expr, $bit_type:ty) => {
println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e));
};
}
macro_rules! dbg_bits { // Macro to wrap a value in 2^n Some() where n is the number of "@" signs.
($e:expr, $bit_type:ty) => { // Increasing the recursion limit is required to evaluate this macro.
println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); macro_rules! many_options {
}; ($value:expr) => { Some($value) };
} ($value:expr, @) => {
Some(Some($value))
};
($value:expr, @ $($more:tt)+) => {
many_options!(many_options!($value, $($more)+), $($more)+)
};
}
// Macro to wrap a value in 2^n Some() where n is the number of "@" signs. fn main() {
// Increasing the recursion limit is required to evaluate this macro. // TOTALLY UNSAFE. Rust provides no guarantees about the bitwise
macro_rules! many_options { // representation of types.
($value:expr) => { Some($value) }; unsafe {
($value:expr, @) => { assert_eq!(many_options!(false), Some(false));
Some(Some($value)) assert_eq!(many_options!(false, @), Some(Some(false)));
}; assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));
($value:expr, @ $($more:tt)+) => {
many_options!(many_options!($value, $($more)+), $($more)+)
};
}
fn main() { println!("Bitwise representation of a chain of 128 Option's.");
// TOTALLY UNSAFE. Rust provides no guarantees about the bitwise dbg_bits!(many_options!(false, @@@@@@@), u8);
// representation of types. dbg_bits!(many_options!(true, @@@@@@@), u8);
unsafe {
assert_eq!(many_options!(false), Some(false));
assert_eq!(many_options!(false, @), Some(Some(false)));
assert_eq!(many_options!(false, @@), Some(Some(Some(Some(false)))));
println!("Bitwise representation of a chain of 128 Option's."); println!("Bitwise representation of a chain of 256 Option's.");
dbg_bits!(many_options!(false, @@@@@@@), u8); dbg_bits!(many_options!(false, @@@@@@@@), u16);
dbg_bits!(many_options!(true, @@@@@@@), u8); dbg_bits!(many_options!(true, @@@@@@@@), u16);
println!("Bitwise representation of a chain of 256 Option's."); println!("Bitwise representation of a chain of 257 Option's.");
dbg_bits!(many_options!(false, @@@@@@@@), u16); dbg_bits!(many_options!(Some(false), @@@@@@@@), u16);
dbg_bits!(many_options!(true, @@@@@@@@), u16); dbg_bits!(many_options!(Some(true), @@@@@@@@), u16);
dbg_bits!(many_options!(None::<bool>, @@@@@@@@), u16);
println!("Bitwise representation of a chain of 257 Option's."); }
dbg_bits!(many_options!(Some(false), @@@@@@@@), u16); }
dbg_bits!(many_options!(Some(true), @@@@@@@@), u16); ```
dbg_bits!(many_options!(None::<bool>, @@@@@@@@), u16);
}
}
```
</details> </details>

View File

@ -31,20 +31,20 @@ fn main() {
* We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe! * We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe!
```rust,editable ```rust,editable
fn main() { fn main() {
let mut s1 = String::from("Hello"); let mut s1 = String::from("Hello");
s1.push(' '); s1.push(' ');
s1.push_str("world"); s1.push_str("world");
// DON'T DO THIS AT HOME! For educational purposes only. // DON'T DO THIS AT HOME! For educational purposes only.
// String provides no guarantees about its layout, so this could lead to // String provides no guarantees about its layout, so this could lead to
// undefined behavior. // undefined behavior.
unsafe { unsafe {
let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1); let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1);
println!("ptr = {ptr:#x}, len = {len}, capacity = {capacity}"); println!("ptr = {ptr:#x}, len = {len}, capacity = {capacity}");
}
} }
} ```
```
</details> </details>

View File

@ -12,22 +12,22 @@ You can destructure arrays, tuples, and slices by matching on their elements:
* Destructuring of slices of unknown length also works with patterns of fixed length. * Destructuring of slices of unknown length also works with patterns of fixed length.
```rust,editable ```rust,editable
fn main() { fn main() {
inspect(&[0, -2, 3]); inspect(&[0, -2, 3]);
inspect(&[0, -2, 3, 4]); inspect(&[0, -2, 3, 4]);
} }
#[rustfmt::skip] #[rustfmt::skip]
fn inspect(slice: &[i32]) { fn inspect(slice: &[i32]) {
println!("Tell me about {slice:?}"); println!("Tell me about {slice:?}");
match slice { match slice {
&[0, y, z] => println!("First is 0, y = {y}, and z = {z}"), &[0, y, z] => println!("First is 0, y = {y}, and z = {z}"),
&[1, ..] => println!("First is 1 and the rest were ignored"), &[1, ..] => println!("First is 1 and the rest were ignored"),
_ => println!("All elements were ignored"), _ => println!("All elements were ignored"),
} }
} }
``` ```
* Create a new pattern using `_` to represent an element. * Create a new pattern using `_` to represent an element.
* Add more values to the array. * Add more values to the array.

View File

@ -38,23 +38,23 @@ fn main() {
* `HashMap` is not defined in the prelude and needs to be brought into scope. * `HashMap` is not defined in the prelude and needs to be brought into scope.
* Try the following lines of code. The first line will see if a book is in the hashmap and if not return an alternative value. The second line will insert the alternative value in the hashmap if the book is not found. * Try the following lines of code. The first line will see if a book is in the hashmap and if not return an alternative value. The second line will insert the alternative value in the hashmap if the book is not found.
```rust,ignore ```rust,ignore
let pc1 = page_counts let pc1 = page_counts
.get("Harry Potter and the Sorcerer's Stone ") .get("Harry Potter and the Sorcerer's Stone ")
.unwrap_or(&336); .unwrap_or(&336);
let pc2 = page_counts let pc2 = page_counts
.entry("The Hunger Games".to_string()) .entry("The Hunger Games".to_string())
.or_insert(374); .or_insert(374);
``` ```
* Unlike `vec!`, there is unfortunately no standard `hashmap!` macro. * Unlike `vec!`, there is unfortunately no standard `hashmap!` macro.
* Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to easily initialize a hash map from a literal array: * Although, since Rust 1.56, HashMap implements [`From<[(K, V); N]>`][1], which allows us to easily initialize a hash map from a literal array:
```rust,ignore ```rust,ignore
let page_counts = HashMap::from([ let page_counts = HashMap::from([
("Harry Potter and the Sorcerer's Stone".to_string(), 336), ("Harry Potter and the Sorcerer's Stone".to_string(), 336),
("The Hunger Games".to_string(), 374), ("The Hunger Games".to_string(), 374),
]); ]);
``` ```
* Alternatively HashMap can be built from any `Iterator` which yields key-value tuples. * Alternatively HashMap can be built from any `Iterator` which yields key-value tuples.
* We are showing `HashMap<String, i32>`, and avoid using `&str` as key to make examples easier. Using references in collections can, of course, be done, * We are showing `HashMap<String, i32>`, and avoid using `&str` as key to make examples easier. Using references in collections can, of course, be done,

View File

@ -42,13 +42,12 @@ fn main() {
* Types that implement a given trait may be of different sizes. This makes it impossible to have things like `Vec<Greet>` in the example above. * Types that implement a given trait may be of different sizes. This makes it impossible to have things like `Vec<Greet>` in the example above.
* `dyn Greet` is a way to tell the compiler about a dynamically sized type that implements `Greet`. * `dyn Greet` is a way to tell the compiler about a dynamically sized type that implements `Greet`.
* In the example, `pets` holds Fat Pointers to objects that implement `Greet`. The Fat Pointer consists of two components, a pointer to the actual object and a pointer to the virtual method table for the `Greet` implementation of that particular object. * In the example, `pets` holds Fat Pointers to objects that implement `Greet`. The Fat Pointer consists of two components, a pointer to the actual object and a pointer to the virtual method table for the `Greet` implementation of that particular object.
* Compare these outputs in the above example:
Compare these outputs in the above example: ```rust,ignore
```rust,ignore println!("{} {}", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>());
println!("{} {}", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>()); println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());
println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>()); println!("{}", std::mem::size_of::<&dyn Greet>());
println!("{}", std::mem::size_of::<&dyn Greet>()); println!("{}", std::mem::size_of::<Box<dyn Greet>>());
println!("{}", std::mem::size_of::<Box<dyn Greet>>()); ```
```
</details> </details>