diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /src/doc/rust-by-example | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc/rust-by-example')
18 files changed, 249 insertions, 180 deletions
diff --git a/src/doc/rust-by-example/src/SUMMARY.md b/src/doc/rust-by-example/src/SUMMARY.md index 9d7001690..b1bcf223d 100644 --- a/src/doc/rust-by-example/src/SUMMARY.md +++ b/src/doc/rust-by-example/src/SUMMARY.md @@ -59,6 +59,7 @@ - [Guards](flow_control/match/guard.md) - [Binding](flow_control/match/binding.md) - [if let](flow_control/if_let.md) + - [let-else](flow_control/let_else.md) - [while let](flow_control/while_let.md) - [Functions](fn.md) diff --git a/src/doc/rust-by-example/src/custom_types/enum.md b/src/doc/rust-by-example/src/custom_types/enum.md index e861df9bf..b7fb7e419 100644 --- a/src/doc/rust-by-example/src/custom_types/enum.md +++ b/src/doc/rust-by-example/src/custom_types/enum.md @@ -1,7 +1,7 @@ # Enums The `enum` keyword allows the creation of a type which may be one of a few -different variants. Any variant which is valid as a `struct` is also valid as +different variants. Any variant which is valid as a `struct` is also valid in an `enum`. ```rust,editable @@ -10,7 +10,7 @@ an `enum`. // `PageLoad != PageUnload` and `KeyPress(char) != Paste(String)`. // Each is different and independent. enum WebEvent { - // An `enum` may either be `unit-like`, + // An `enum` variant may either be `unit-like`, PageLoad, PageUnload, // like tuple structs, @@ -26,7 +26,7 @@ fn inspect(event: WebEvent) { match event { WebEvent::PageLoad => println!("page loaded"), WebEvent::PageUnload => println!("page unloaded"), - // Destructure `c` from inside the `enum`. + // Destructure `c` from inside the `enum` variant. WebEvent::KeyPress(c) => println!("pressed '{}'.", c), WebEvent::Paste(s) => println!("pasted \"{}\".", s), // Destructure `Click` into `x` and `y`. diff --git a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md index 117333f12..4c1844a20 100644 --- a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md +++ b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md @@ -63,17 +63,17 @@ fn main() { To make sure that an `Option` contains a value, we can use `get_or_insert` to modify it in place with a fallback value, as is shown in the following example. Note that `get_or_insert` eagerly evaluates its parameter, so variable `apple` is moved: ```rust,editable -#[derive(Debug)] +#[derive(Debug)] enum Fruit { Apple, Orange, Banana, Kiwi, Lemon } fn main() { let mut my_fruit: Option<Fruit> = None; let apple = Fruit::Apple; let first_available_fruit = my_fruit.get_or_insert(apple); - println!("my_fruit is: {:?}", first_available_fruit); println!("first_available_fruit is: {:?}", first_available_fruit); - // my_fruit is: Apple + println!("my_fruit is: {:?}", my_fruit); // first_available_fruit is: Apple + // my_fruit is: Some(Apple) //println!("Variable named `apple` is moved: {:?}", apple); // TODO: uncomment the line above to see the compiler error } @@ -94,11 +94,11 @@ fn main() { }; let first_available_fruit = my_fruit .get_or_insert_with(get_lemon_as_fallback); - println!("my_fruit is: {:?}", first_available_fruit); println!("first_available_fruit is: {:?}", first_available_fruit); + println!("my_fruit is: {:?}", my_fruit); // Providing lemon as fallback - // my_fruit is: Lemon // first_available_fruit is: Lemon + // my_fruit is: Some(Lemon) // If the Option has a value, it is left unchanged, and the closure is not invoked let mut my_apple = Some(Fruit::Apple); diff --git a/src/doc/rust-by-example/src/flow_control/let_else.md b/src/doc/rust-by-example/src/flow_control/let_else.md new file mode 100644 index 000000000..bc21723c7 --- /dev/null +++ b/src/doc/rust-by-example/src/flow_control/let_else.md @@ -0,0 +1,60 @@ +# let-else + + +> 🛈 stable since: rust 1.65 + + +With `let`-`else`, a refutable pattern can match and bind variables +in the surrounding scope like a normal `let`, or else diverge (e.g. `break`, +`return`, `panic!`) when the pattern doesn't match. + +```rust +use std::str::FromStr; + +fn get_count_item(s: &str) -> (u64, &str) { + let mut it = s.split(' '); + let (Some(count_str), Some(item)) = (it.next(), it.next()) else { + panic!("Can't segment count item pair: '{s}'"); + }; + let Ok(count) = u64::from_str(count_str) else { + panic!("Can't parse integer: '{count_str}'"); + }; + (count, item) +} + +assert_eq!(get_count_item("3 chairs"), (3, "chairs")); +``` + +The scope of name bindings is the main thing that makes this different from +`match` or `if let`-`else` expressions. You could previously approximate these +patterns with an unfortunate bit of repetition and an outer `let`: + +```rust +# use std::str::FromStr; +# +# fn get_count_item(s: &str) -> (u64, &str) { +# let mut it = s.split(' '); + let (count_str, item) = match (it.next(), it.next()) { + (Some(count_str), Some(item)) => (count_str, item), + _ => panic!("Can't segment count item pair: '{s}'"), + }; + let count = if let Ok(count) = u64::from_str(count_str) { + count + } else { + panic!("Can't parse integer: '{count_str}'"); + }; +# (count, item) +# } +# +# assert_eq!(get_count_item("3 chairs"), (3, "chairs")); +``` + +### See also: + +[option][option], [match][match], [if let][if_let] and the [let-else RFC][let_else_rfc]. + + +[match]: ./match.md +[if_let]: ./if_let.md +[let_else_rfc]: https://rust-lang.github.io/rfcs/3137-let-else.html +[option]: ../std/option.md
\ No newline at end of file diff --git a/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_any.md b/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_any.md index fe7fc39f8..4c19caccc 100644 --- a/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_any.md +++ b/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_any.md @@ -27,7 +27,7 @@ fn main() { // `iter()` for vecs yields `&i32`. Destructure to `i32`. println!("2 in vec1: {}", vec1.iter() .any(|&x| x == 2)); // `into_iter()` for vecs yields `i32`. No destructuring required. - println!("2 in vec2: {}", vec2.into_iter().any(| x| x == 2)); + println!("2 in vec2: {}", vec2.into_iter().any(|x| x == 2)); // `iter()` only borrows `vec1` and its elements, so they can be used again println!("vec1 len: {}", vec1.len()); diff --git a/src/doc/rust-by-example/src/fn/diverging.md b/src/doc/rust-by-example/src/fn/diverging.md index 52e1f819a..4bc7c9fea 100644 --- a/src/doc/rust-by-example/src/fn/diverging.md +++ b/src/doc/rust-by-example/src/fn/diverging.md @@ -21,8 +21,8 @@ fn some_fn() { } fn main() { - let a: () = some_fn(); - println!("This function returns and you can see this line.") + let _a: () = some_fn(); + println!("This function returns and you can see this line."); } ``` diff --git a/src/doc/rust-by-example/src/hello.md b/src/doc/rust-by-example/src/hello.md index 2a8d3153f..4aaddeb1f 100644 --- a/src/doc/rust-by-example/src/hello.md +++ b/src/doc/rust-by-example/src/hello.md @@ -3,18 +3,19 @@ This is the source code of the traditional Hello World program. ```rust,editable -// This is a comment, and is ignored by the compiler +// This is a comment, and is ignored by the compiler. // You can test this code by clicking the "Run" button over there -> -// or if you prefer to use your keyboard, you can use the "Ctrl + Enter" shortcut +// or if you prefer to use your keyboard, you can use the "Ctrl + Enter" +// shortcut. // This code is editable, feel free to hack it! // You can always return to the original code by clicking the "Reset" button -> -// This is the main function +// This is the main function. fn main() { - // Statements here are executed when the compiled binary is called + // Statements here are executed when the compiled binary is called. - // Print text to the console + // Print text to the console. println!("Hello World!"); } ``` @@ -38,8 +39,7 @@ Hello World! ### Activity Click 'Run' above to see the expected output. Next, add a new -line with a second `println!` macro so that the output -shows: +line with a second `println!` macro so that the output shows: ```text Hello World! diff --git a/src/doc/rust-by-example/src/hello/comment.md b/src/doc/rust-by-example/src/hello/comment.md index 8cd1ccf55..5027f0a22 100644 --- a/src/doc/rust-by-example/src/hello/comment.md +++ b/src/doc/rust-by-example/src/hello/comment.md @@ -4,30 +4,29 @@ Any program requires comments, and Rust supports a few different varieties: * *Regular comments* which are ignored by the compiler: - * `// Line comments which go to the end of the line.` - * `/* Block comments which go to the closing delimiter. */` -* *Doc comments* which are parsed into HTML library - [documentation][docs]: - * `/// Generate library docs for the following item.` - * `//! Generate library docs for the enclosing item.` + * `// Line comments which go to the end of the line.` + * `/* Block comments which go to the closing delimiter. */` +* *Doc comments* which are parsed into HTML library [documentation][docs]: + * `/// Generate library docs for the following item.` + * `//! Generate library docs for the enclosing item.` ```rust,editable fn main() { - // This is an example of a line comment - // There are two slashes at the beginning of the line - // And nothing written inside these will be read by the compiler + // This is an example of a line comment. + // There are two slashes at the beginning of the line. + // And nothing written inside these will be read by the compiler. // println!("Hello, world!"); // Run it. See? Now try deleting the two slashes, and run it again. - /* + /* * This is another type of comment, a block comment. In general, - * line comments are the recommended comment style. But - * block comments are extremely useful for temporarily disabling - * chunks of code. /* Block comments can be /* nested, */ */ - * so it takes only a few keystrokes to comment out everything - * in this main() function. /*/*/* Try it yourself! */*/*/ + * line comments are the recommended comment style. But block comments + * are extremely useful for temporarily disabling chunks of code. + * /* Block comments can be /* nested, */ */ so it takes only a few + * keystrokes to comment out everything in this main() function. + * /*/*/* Try it yourself! */*/*/ */ /* @@ -41,7 +40,6 @@ fn main() { let x = 5 + /* 90 + */ 5; println!("Is `x` 10 or 100? x = {}", x); } - ``` ### See also: diff --git a/src/doc/rust-by-example/src/hello/print.md b/src/doc/rust-by-example/src/hello/print.md index cce838fc2..55f6ed520 100644 --- a/src/doc/rust-by-example/src/hello/print.md +++ b/src/doc/rust-by-example/src/hello/print.md @@ -1,12 +1,14 @@ # Formatted print -Printing is handled by a series of [`macros`][macros] defined in [`std::fmt`][fmt] -some of which include: +Printing is handled by a series of [`macros`][macros] defined in +[`std::fmt`][fmt] some of which include: * `format!`: write formatted text to [`String`][string] -* `print!`: same as `format!` but the text is printed to the console (io::stdout). +* `print!`: same as `format!` but the text is printed to the console + (io::stdout). * `println!`: same as `print!` but a newline is appended. -* `eprint!`: same as `print!` but the text is printed to the standard error (io::stderr). +* `eprint!`: same as `print!` but the text is printed to the standard error + (io::stderr). * `eprintln!`: same as `eprint!` but a newline is appended. All parse text in the same fashion. As a plus, Rust checks formatting @@ -20,7 +22,7 @@ fn main() { // Positional arguments can be used. Specifying an integer inside `{}` // determines which additional argument will be replaced. Arguments start - // at 0 immediately after the format string + // at 0 immediately after the format string. println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob"); // As can named arguments. @@ -29,13 +31,13 @@ fn main() { subject="the quick brown fox", verb="jumps over"); - // Different formatting can be invoked by specifying the format character after a - // `:`. - println!("Base 10: {}", 69420); //69420 - println!("Base 2 (binary): {:b}", 69420); //10000111100101100 - println!("Base 8 (octal): {:o}", 69420); //207454 - println!("Base 16 (hexadecimal): {:x}", 69420); //10f2c - println!("Base 16 (hexadecimal): {:X}", 69420); //10F2C + // Different formatting can be invoked by specifying the format character + // after a `:`. + println!("Base 10: {}", 69420); // 69420 + println!("Base 2 (binary): {:b}", 69420); // 10000111100101100 + println!("Base 8 (octal): {:o}", 69420); // 207454 + println!("Base 16 (hexadecimal): {:x}", 69420); // 10f2c + println!("Base 16 (hexadecimal): {:X}", 69420); // 10F2C // You can right-justify text with a specified width. This will @@ -43,32 +45,31 @@ fn main() { println!("{number:>5}", number=1); // You can pad numbers with extra zeroes, - //and left-adjust by flipping the sign. This will output "10000". + // and left-adjust by flipping the sign. This will output "10000". println!("{number:0<5}", number=1); - // You can use named arguments in the format specifier by appending a `$` + // You can use named arguments in the format specifier by appending a `$`. println!("{number:0>width$}", number=1, width=5); - // Rust even checks to make sure the correct number of arguments are - // used. + // Rust even checks to make sure the correct number of arguments are used. println!("My name is {0}, {1} {0}", "Bond"); // FIXME ^ Add the missing argument: "James" // Only types that implement fmt::Display can be formatted with `{}`. User- - // defined types do not implement fmt::Display by default + // defined types do not implement fmt::Display by default. - #[allow(dead_code)] + #[allow(dead_code)] // disable `dead_code` which warn against unused module struct Structure(i32); // This will not compile because `Structure` does not implement - // fmt::Display + // fmt::Display. //println!("This struct `{}` won't print...", Structure(3)); // TODO ^ Try uncommenting this line // For Rust 1.58 and above, you can directly capture the argument from a // surrounding variable. Just like the above, this will output - // " 1". 4 white spaces and a "1". + // " 1", 4 white spaces and a "1". let number: f64 = 1.0; let width: usize = 5; println!("{number:>width$}"); @@ -80,7 +81,7 @@ of text. The base form of two important ones are listed below: * `fmt::Debug`: Uses the `{:?}` marker. Format text for debugging purposes. * `fmt::Display`: Uses the `{}` marker. Format text in a more elegant, user -friendly fashion. + friendly fashion. Here, we used `fmt::Display` because the std library provides implementations for these types. To print text for custom types, more steps are required. @@ -88,21 +89,22 @@ for these types. To print text for custom types, more steps are required. Implementing the `fmt::Display` trait automatically implements the [`ToString`] trait which allows us to [convert] the type to [`String`][string]. +In *line 46*, `#[allow(dead_code)]` is an [attribute] which only apply to the module after it. + ### Activities - * Fix the issue in the above code (see FIXME) so that it runs without - error. - * Try uncommenting the line that attempts to format the `Structure` struct (see TODO) - * Add a `println!` macro call that prints: `Pi is roughly 3.142` by controlling - the number of decimal places shown. For the purposes of this exercise, - use `let pi = 3.141592` as an estimate for pi. (Hint: you may need to - check the [`std::fmt`][fmt] documentation for setting the number of - decimals to display) +* Fix the issue in the above code (see FIXME) so that it runs without + error. +* Try uncommenting the line that attempts to format the `Structure` struct + (see TODO) +* Add a `println!` macro call that prints: `Pi is roughly 3.142` by controlling + the number of decimal places shown. For the purposes of this exercise, use + `let pi = 3.141592` as an estimate for pi. (Hint: you may need to check the + [`std::fmt`][fmt] documentation for setting the number of decimals to display) ### See also: -[`std::fmt`][fmt], [`macros`][macros], [`struct`][structs], -and [`traits`][traits] +[`std::fmt`][fmt], [`macros`][macros], [`struct`][structs], [`traits`][traits], and [`dead_code`][dead_code] [fmt]: https://doc.rust-lang.org/std/fmt/ [macros]: ../macros.md @@ -111,3 +113,5 @@ and [`traits`][traits] [traits]: https://doc.rust-lang.org/std/fmt/#formatting-traits [`ToString`]: https://doc.rust-lang.org/std/string/trait.ToString.html [convert]: ../conversion/string.md +[attribute]: ../attribute.md +[dead_code]: ../attribute/unused.md diff --git a/src/doc/rust-by-example/src/hello/print/fmt.md b/src/doc/rust-by-example/src/hello/print/fmt.md index 82c3e0145..5332b4903 100644 --- a/src/doc/rust-by-example/src/hello/print/fmt.md +++ b/src/doc/rust-by-example/src/hello/print/fmt.md @@ -3,8 +3,7 @@ We've seen that formatting is specified via a *format string*: * `format!("{}", foo)` -> `"3735928559"` -* `format!("0x{:X}", foo)` -> - [`"0xDEADBEEF"`][deadbeef] +* `format!("0x{:X}", foo)` -> [`"0xDEADBEEF"`][deadbeef] * `format!("0o{:o}", foo)` -> `"0o33653337357"` The same variable (`foo`) can be formatted differently depending on which @@ -26,13 +25,13 @@ struct City { } impl Display for City { - // `f` is a buffer, and this method must write the formatted string into it + // `f` is a buffer, and this method must write the formatted string into it. fn fmt(&self, f: &mut Formatter) -> fmt::Result { let lat_c = if self.lat >= 0.0 { 'N' } else { 'S' }; let lon_c = if self.lon >= 0.0 { 'E' } else { 'W' }; // `write!` is like `format!`, but it will write the formatted string - // into a buffer (the first argument) + // into a buffer (the first argument). write!(f, "{}: {:.3}°{} {:.3}°{}", self.name, self.lat.abs(), lat_c, self.lon.abs(), lon_c) } @@ -69,6 +68,7 @@ You can view a [full list of formatting traits][fmt_traits] and their argument types in the [`std::fmt`][fmt] documentation. ### Activity + Add an implementation of the `fmt::Display` trait for the `Color` struct above so that the output displays as: @@ -79,8 +79,9 @@ RGB (0, 0, 0) 0x000000 ``` Two hints if you get stuck: - * You [may need to list each color more than once][named_parameters], - * You can [pad with zeros to a width of 2][fmt_width] with `:0>2`. + +* You [may need to list each color more than once][named_parameters]. +* You can [pad with zeros to a width of 2][fmt_width] with `:0>2`. ### See also: diff --git a/src/doc/rust-by-example/src/hello/print/print_debug.md b/src/doc/rust-by-example/src/hello/print/print_debug.md index 161b0b772..03b1975ee 100644 --- a/src/doc/rust-by-example/src/hello/print/print_debug.md +++ b/src/doc/rust-by-example/src/hello/print/print_debug.md @@ -43,15 +43,15 @@ fn main() { // `Structure` is printable! println!("Now {:?} will print!", Structure(3)); - + // The problem with `derive` is there is no control over how // the results look. What if I want this to just show a `7`? println!("Now {:?} will print!", Deep(Structure(7))); } ``` -So `fmt::Debug` definitely makes this printable but sacrifices some -elegance. Rust also provides "pretty printing" with `{:#?}`. +So `fmt::Debug` definitely makes this printable but sacrifices some elegance. +Rust also provides "pretty printing" with `{:#?}`. ```rust,editable #[derive(Debug)] diff --git a/src/doc/rust-by-example/src/hello/print/print_display.md b/src/doc/rust-by-example/src/hello/print/print_display.md index fdae9648a..5d8a45b12 100644 --- a/src/doc/rust-by-example/src/hello/print/print_display.md +++ b/src/doc/rust-by-example/src/hello/print/print_display.md @@ -41,7 +41,7 @@ or for any other generic containers. `fmt::Debug` must then be used for these generic cases. This is not a problem though because for any new *container* type which is -*not* generic,`fmt::Display` can be implemented. +*not* generic, `fmt::Display` can be implemented. ```rust,editable use std::fmt; // Import `fmt` @@ -66,7 +66,7 @@ struct Point2D { y: f64, } -// Similarly, implement `Display` for `Point2D` +// Similarly, implement `Display` for `Point2D`. impl fmt::Display for Point2D { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Customize so only `x` and `y` are denoted. @@ -100,10 +100,9 @@ fn main() { } ``` -So, `fmt::Display` has been implemented but `fmt::Binary` has not, and -therefore cannot be used. `std::fmt` has many such [`traits`][traits] and -each requires its own implementation. This is detailed further in -[`std::fmt`][fmt]. +So, `fmt::Display` has been implemented but `fmt::Binary` has not, and therefore +cannot be used. `std::fmt` has many such [`traits`][traits] and each requires +its own implementation. This is detailed further in [`std::fmt`][fmt]. ### Activity diff --git a/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md b/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md index 63e400b6a..d07316b72 100644 --- a/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md +++ b/src/doc/rust-by-example/src/hello/print/print_display/testcase_list.md @@ -52,7 +52,8 @@ fn main() { ### Activity -Try changing the program so that the index of each element in the vector is also printed. The new output should look like this: +Try changing the program so that the index of each element in the vector is also +printed. The new output should look like this: ```rust,ignore [0: 1, 1: 2, 2: 3] diff --git a/src/doc/rust-by-example/src/primitives.md b/src/doc/rust-by-example/src/primitives.md index 6b579e5ea..6560e99e9 100644 --- a/src/doc/rust-by-example/src/primitives.md +++ b/src/doc/rust-by-example/src/primitives.md @@ -2,28 +2,27 @@ Rust provides access to a wide variety of `primitives`. A sample includes: - ### Scalar Types -* signed integers: `i8`, `i16`, `i32`, `i64`, `i128` and `isize` (pointer size) -* unsigned integers: `u8`, `u16`, `u32`, `u64`, `u128` and `usize` (pointer +* Signed integers: `i8`, `i16`, `i32`, `i64`, `i128` and `isize` (pointer size) +* Unsigned integers: `u8`, `u16`, `u32`, `u64`, `u128` and `usize` (pointer size) -* floating point: `f32`, `f64` +* Floating point: `f32`, `f64` * `char` Unicode scalar values like `'a'`, `'α'` and `'∞'` (4 bytes each) * `bool` either `true` or `false` -* and the unit type `()`, whose only possible value is an empty tuple: `()` +* The unit type `()`, whose only possible value is an empty tuple: `()` -Despite the value of a unit type being a tuple, it is not considered a -compound type because it does not contain multiple values. +Despite the value of a unit type being a tuple, it is not considered a compound +type because it does not contain multiple values. ### Compound Types -* arrays like `[1, 2, 3]` -* tuples like `(1, true)` +* Arrays like `[1, 2, 3]` +* Tuples like `(1, true)` -Variables can always be *type annotated*. Numbers may additionally be -annotated via a *suffix* or *by default*. Integers default to `i32` and -floats to `f64`. Note that Rust can also infer types from context. +Variables can always be *type annotated*. Numbers may additionally be annotated +via a *suffix* or *by default*. Integers default to `i32` and floats to `f64`. +Note that Rust can also infer types from context. ```rust,editable,ignore,mdbook-runnable fn main() { @@ -36,18 +35,18 @@ fn main() { // Or a default will be used. let default_float = 3.0; // `f64` let default_integer = 7; // `i32` - - // A type can also be inferred from context - let mut inferred_type = 12; // Type i64 is inferred from another line + + // A type can also be inferred from context. + let mut inferred_type = 12; // Type i64 is inferred from another line. inferred_type = 4294967296i64; - + // A mutable variable's value can be changed. let mut mutable = 12; // Mutable `i32` mutable = 21; - + // Error! The type of a variable can't be changed. mutable = true; - + // Variables can be overwritten with shadowing. let mutable = true; } @@ -55,7 +54,8 @@ fn main() { ### See also: -[the `std` library][std], [`mut`][mut], [`inference`][inference], and [`shadowing`][shadowing] +[the `std` library][std], [`mut`][mut], [`inference`][inference], and +[`shadowing`][shadowing] [std]: https://doc.rust-lang.org/std/ [mut]: variable_bindings/mut.md diff --git a/src/doc/rust-by-example/src/primitives/array.md b/src/doc/rust-by-example/src/primitives/array.md index 0f56182cd..3811bb6d7 100644 --- a/src/doc/rust-by-example/src/primitives/array.md +++ b/src/doc/rust-by-example/src/primitives/array.md @@ -5,66 +5,65 @@ memory. Arrays are created using brackets `[]`, and their length, which is known at compile time, is part of their type signature `[T; length]`. Slices are similar to arrays, but their length is not known at compile time. -Instead, a slice is a two-word object, the first word is a pointer to the data, -and the second word is the length of the slice. The word size is the same as -usize, determined by the processor architecture e.g. 64 bits on an x86-64. -Slices can be used to borrow a section of an array, and have the type signature -`&[T]`. +Instead, a slice is a two-word object; the first word is a pointer to the data, +the second word the length of the slice. The word size is the same as usize, +determined by the processor architecture, e.g. 64 bits on an x86-64. Slices can +be used to borrow a section of an array and have the type signature `&[T]`. ```rust,editable,ignore,mdbook-runnable use std::mem; -// This function borrows a slice +// This function borrows a slice. fn analyze_slice(slice: &[i32]) { - println!("first element of the slice: {}", slice[0]); - println!("the slice has {} elements", slice.len()); + println!("First element of the slice: {}", slice[0]); + println!("The slice has {} elements", slice.len()); } fn main() { - // Fixed-size array (type signature is superfluous) + // Fixed-size array (type signature is superfluous). let xs: [i32; 5] = [1, 2, 3, 4, 5]; - // All elements can be initialized to the same value + // All elements can be initialized to the same value. let ys: [i32; 500] = [0; 500]; - // Indexing starts at 0 - println!("first element of the array: {}", xs[0]); - println!("second element of the array: {}", xs[1]); + // Indexing starts at 0. + println!("First element of the array: {}", xs[0]); + println!("Second element of the array: {}", xs[1]); - // `len` returns the count of elements in the array - println!("number of elements in array: {}", xs.len()); + // `len` returns the count of elements in the array. + println!("Number of elements in array: {}", xs.len()); - // Arrays are stack allocated - println!("array occupies {} bytes", mem::size_of_val(&xs)); + // Arrays are stack allocated. + println!("Array occupies {} bytes", mem::size_of_val(&xs)); - // Arrays can be automatically borrowed as slices - println!("borrow the whole array as a slice"); + // Arrays can be automatically borrowed as slices. + println!("Borrow the whole array as a slice."); analyze_slice(&xs); - // Slices can point to a section of an array - // They are of the form [starting_index..ending_index] - // starting_index is the first position in the slice - // ending_index is one more than the last position in the slice - println!("borrow a section of the array as a slice"); + // Slices can point to a section of an array. + // They are of the form [starting_index..ending_index]. + // `starting_index` is the first position in the slice. + // `ending_index` is one more than the last position in the slice. + println!("Borrow a section of the array as a slice."); analyze_slice(&ys[1 .. 4]); - // Example of empty slice `&[]` + // Example of empty slice `&[]`: let empty_array: [u32; 0] = []; assert_eq!(&empty_array, &[]); - assert_eq!(&empty_array, &[][..]); // same but more verbose + assert_eq!(&empty_array, &[][..]); // Same but more verbose // Arrays can be safely accessed using `.get`, which returns an // `Option`. This can be matched as shown below, or used with // `.expect()` if you would like the program to exit with a nice // message instead of happily continue. - for i in 0..xs.len() + 1 { // OOPS, one element too far + for i in 0..xs.len() + 1 { // Oops, one element too far! match xs.get(i) { Some(xval) => println!("{}: {}", i, xval), None => println!("Slow down! {} is too far!", i), } } - // Out of bound indexing causes runtime error + // Out of bound indexing causes runtime error. //println!("{}", xs[5]); } ``` diff --git a/src/doc/rust-by-example/src/primitives/literals.md b/src/doc/rust-by-example/src/primitives/literals.md index 4927e6af8..dfe4e3a88 100644 --- a/src/doc/rust-by-example/src/primitives/literals.md +++ b/src/doc/rust-by-example/src/primitives/literals.md @@ -9,12 +9,15 @@ notation using these prefixes respectively: `0x`, `0o` or `0b`. Underscores can be inserted in numeric literals to improve readability, e.g. `1_000` is the same as `1000`, and `0.000_001` is the same as `0.000001`. +Rust also supports scientific [E-notation][enote], e.g. `1e6`, `7.6e-4`. The +associated type is `f64`. + We need to tell the compiler the type of the literals we use. For now, we'll use the `u32` suffix to indicate that the literal is an unsigned 32-bit integer, and the `i32` suffix to indicate that it's a signed 32-bit integer. -The operators available and their precedence [in Rust][rust op-prec] are similar to other -[C-like languages][op-prec]. +The operators available and their precedence [in Rust][rust op-prec] are similar +to other [C-like languages][op-prec]. ```rust,editable fn main() { @@ -25,6 +28,9 @@ fn main() { println!("1 - 2 = {}", 1i32 - 2); // TODO ^ Try changing `1i32` to `1u32` to see why the type is important + // Scientific notation + println!("1e4 is {}, -2.5e-3 is {}", 1e4, -2.5e-3); + // Short-circuiting boolean logic println!("true AND false is {}", true && false); println!("true OR false is {}", true || false); @@ -42,5 +48,6 @@ fn main() { } ``` +[enote]: https://en.wikipedia.org/wiki/Scientific_notation#E_notation [rust op-prec]: https://doc.rust-lang.org/reference/expressions.html#expression-precedence [op-prec]: https://en.wikipedia.org/wiki/Operator_precedence#Programming_languages diff --git a/src/doc/rust-by-example/src/primitives/tuples.md b/src/doc/rust-by-example/src/primitives/tuples.md index f4b59c04b..e745d89be 100644 --- a/src/doc/rust-by-example/src/primitives/tuples.md +++ b/src/doc/rust-by-example/src/primitives/tuples.md @@ -6,9 +6,9 @@ using parentheses `()`, and each tuple itself is a value with type signature use tuples to return multiple values, as tuples can hold any number of values. ```rust,editable -// Tuples can be used as function arguments and as return values +// Tuples can be used as function arguments and as return values. fn reverse(pair: (i32, bool)) -> (bool, i32) { - // `let` can be used to bind the members of a tuple to variables + // `let` can be used to bind the members of a tuple to variables. let (int_param, bool_param) = pair; (bool_param, int_param) @@ -19,38 +19,38 @@ fn reverse(pair: (i32, bool)) -> (bool, i32) { struct Matrix(f32, f32, f32, f32); fn main() { - // A tuple with a bunch of different types + // A tuple with a bunch of different types. let long_tuple = (1u8, 2u16, 3u32, 4u64, -1i8, -2i16, -3i32, -4i64, 0.1f32, 0.2f64, 'a', true); - // Values can be extracted from the tuple using tuple indexing - println!("long tuple first value: {}", long_tuple.0); - println!("long tuple second value: {}", long_tuple.1); + // Values can be extracted from the tuple using tuple indexing. + println!("Long tuple first value: {}", long_tuple.0); + println!("Long tuple second value: {}", long_tuple.1); - // Tuples can be tuple members + // Tuples can be tuple members. let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16); - // Tuples are printable + // Tuples are printable. println!("tuple of tuples: {:?}", tuple_of_tuples); - - // But long Tuples (more than 12 elements) cannot be printed - // let too_long_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13); - // println!("too long tuple: {:?}", too_long_tuple); + + // But long Tuples (more than 12 elements) cannot be printed. + //let too_long_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13); + //println!("Too long tuple: {:?}", too_long_tuple); // TODO ^ Uncomment the above 2 lines to see the compiler error let pair = (1, true); - println!("pair is {:?}", pair); + println!("Pair is {:?}", pair); - println!("the reversed pair is {:?}", reverse(pair)); + println!("Uhe reversed pair is {:?}", reverse(pair)); // To create one element tuples, the comma is required to tell them apart - // from a literal surrounded by parentheses - println!("one element tuple: {:?}", (5u32,)); - println!("just an integer: {:?}", (5u32)); + // from a literal surrounded by parentheses. + println!("One element tuple: {:?}", (5u32,)); + println!("Just an integer: {:?}", (5u32)); - //tuples can be destructured to create bindings + // Tuples can be destructured to create bindings. let tuple = (1, "hello", 4.5, true); let (a, b, c, d) = tuple; @@ -58,40 +58,39 @@ fn main() { let matrix = Matrix(1.1, 1.2, 2.1, 2.2); println!("{:?}", matrix); - } ``` ### Activity - 1. *Recap*: Add the `fmt::Display` trait to the `Matrix` struct in the above example, - so that if you switch from printing the debug format `{:?}` to the display - format `{}`, you see the following output: - - ```text - ( 1.1 1.2 ) - ( 2.1 2.2 ) - ``` - - You may want to refer back to the example for [print display][print_display]. - 2. Add a `transpose` function using the `reverse` function as a template, which - accepts a matrix as an argument, and returns a matrix in which two elements - have been swapped. For example: - - ```rust,ignore - println!("Matrix:\n{}", matrix); - println!("Transpose:\n{}", transpose(matrix)); - ``` - - results in the output: - - ```text - Matrix: - ( 1.1 1.2 ) - ( 2.1 2.2 ) - Transpose: - ( 1.1 2.1 ) - ( 1.2 2.2 ) - ``` +1. *Recap*: Add the `fmt::Display` trait to the `Matrix` struct in the above + example, so that if you switch from printing the debug format `{:?}` to the + display format `{}`, you see the following output: + + ```text + ( 1.1 1.2 ) + ( 2.1 2.2 ) + ``` + + You may want to refer back to the example for [print display][print_display]. +2. Add a `transpose` function using the `reverse` function as a template, which + accepts a matrix as an argument, and returns a matrix in which two elements + have been swapped. For example: + + ```rust,ignore + println!("Matrix:\n{}", matrix); + println!("Transpose:\n{}", transpose(matrix)); + ``` + + Results in the output: + + ```text + Matrix: + ( 1.1 1.2 ) + ( 2.1 2.2 ) + Transpose: + ( 1.1 2.1 ) + ( 1.2 2.2 ) + ``` [print_display]: ../hello/print/print_display.md diff --git a/src/doc/rust-by-example/src/types/alias.md b/src/doc/rust-by-example/src/types/alias.md index 1d004587c..a2e02ac1a 100644 --- a/src/doc/rust-by-example/src/types/alias.md +++ b/src/doc/rust-by-example/src/types/alias.md @@ -24,8 +24,8 @@ fn main() { } ``` -The main use of aliases is to reduce boilerplate; for example the `IoResult<T>` type -is an alias for the `Result<T, IoError>` type. +The main use of aliases is to reduce boilerplate; for example the `io::Result<T>` type +is an alias for the `Result<T, io::Error>` type. ### See also: |