Compare commits

...

34 Commits

Author SHA1 Message Date
Veera c3021dba36
Merge e4e9ba7866 into cb0a24007f 2024-04-26 14:51:14 -07:00
Carol (Nichols || Goulding) cb0a24007f Snapshot changes to ch7 to consider sending to nostarch 2024-04-25 17:04:25 -04:00
Carol (Nichols || Goulding) f954cb859f Snapshot changes to generated ch7 that SHOULDN'T be sent to nostarch
This snapshot contains line wrapping problems, irrelevant comments,
extraneous output lines, and differences we're going to allow between
the online and print version.

The intention is to make this a baseline commit for chapter 7 that we
can diff against to find changes to consider sending to nostarch as tiny
tweaks.
2024-04-25 17:04:25 -04:00
Carol (Nichols || Goulding) 98165c4279 Backport changes from print for ch7 2024-04-25 17:04:25 -04:00
Chris Krycho d207d894cc
Merge pull request #3898 from rust-lang/chriskrycho/crab-pincers
Ch. 2: intentionally use `{}` at first
2024-04-19 13:48:19 -06:00
Chris Krycho 0b4e00345c
Merge pull request #3897 from nyurik/redirect-lints
Inline fmt lints for `redirects/`
2024-04-19 13:48:13 -06:00
Chris Krycho 502d012cab Ch. 2: intentionally use `{}` at first
This supports the prose in the guessing game tutorial, which uses this
as a way of teaching where you can do `{foo}` and where you cannot.
2024-04-19 13:42:05 -06:00
Yuri Astrakhan c13271897d Inline fmt lints for `redirects/`
I couldn't find any documentation of how `redirects/` dir is being used,
but fixed inlined format args for consistency
2024-04-19 15:40:41 -04:00
Chris Krycho 8a79f3e15d
Merge pull request #3287 from bravequickcleverfibreyarn/listing-12-02
ch12-03: `expect` is not used multitude times by this chapter
2024-04-19 13:36:49 -06:00
Chris Krycho 62516ee9e3
Merge pull request #3896 from nyurik/inline-fmt-arg
Inline format args to `tools/src`
2024-04-19 13:36:10 -06:00
Chris Krycho f3d9661aff
Merge pull request #3290 from agotsis/closure-grammar
Improve awkward phrasing around the kinds of closures
2024-04-19 13:35:36 -06:00
Chris Krycho 54726034c5
Ch. 12.3: be clearer about how `expect` was used 2024-04-19 13:35:31 -06:00
Chris Krycho 8264d69aa6
Ch. 13: `unwrap_or_else` takes all three kinds of closures 2024-04-19 13:31:53 -06:00
Yuri Astrakhan c5211edeec Apply clippy::uninlined_format_args fix 2024-04-19 15:20:22 -04:00
Chris Krycho 0bcde15346
Merge pull request #3890 from rust-lang/push-vmxrspyskulq
Ch. 14: clarify workspace dependency reuse
2024-04-19 13:19:52 -06:00
Chris Krycho 50149d92e0
Merge pull request #3281 from thedumbsloth/function_name_fix_7.3
Edit on line no. 153. Replaced fn add_to_waitlist with fn eat_at_restaurant.
2024-04-19 13:12:00 -06:00
Chris Krycho 874d9a2131
Merge pull request #3895 from rust-lang/chriskrycho/vhb
Ch. 2: less ambiguity about numbers
2024-04-19 13:06:51 -06:00
Chris Krycho 523d960984 Merge `main` into `chriskrycho/vhb` 2024-04-19 13:02:06 -06:00
Chris Krycho 0729f34edc Ch. 2: Further simplify language about numbers 2024-04-19 12:56:58 -06:00
Chris Krycho f9d4e058a9
Merge pull request #3363 from vinsburg/patch-4
Clarified first slices paragraph
2024-04-19 12:51:38 -06:00
Chris Krycho 82df41e8bd Ch. 4: include link forward to collections
Remove the additional, extraneous info from the Ch. 4. section 3 intro.
2024-04-19 12:49:38 -06:00
Chris Krycho 162d540045
Merge pull request #3385 from nyurik/inlinefmt2
Inline all format arguments
2024-04-19 12:03:47 -06:00
Chris Krycho 6196a0ab45 Merge `main` into `nyurik:inlinefmt2` 2024-04-19 11:57:29 -06:00
Chris Krycho 96224742f3
Merge pull request #3048 from nyurik/format-ident
Use v1.58 captured ident formatting in examples
2024-04-19 11:49:12 -06:00
Chris Krycho 1221096717 Ch. 14: clarify workspace dependency reuse
Fixes #3141
2024-04-17 12:35:06 -06:00
Yuri Astrakhan a786ec4a2b Use v1.58 captured ident formatting in examples
Per https://github.com/rust-lang/book/issues/3047, use captured identifiers instead of the positional ones for some examples, e.g.

```diff
-  println!("Worker {} got a job; executing.", id);
+  println!("Worker {id} got a job; executing.");
```
2023-10-30 11:54:45 -04:00
Yuri Astrakhan f55ac5d8fa Inline all format arguments
The inlined format arguments are a bit easier to understand,
especially for those familiar with the other languages (python, js).
2023-10-30 11:54:36 -04:00
Veera e4e9ba7866 Refutability: Mention `let`-`else` statement 2023-07-14 18:29:20 -04:00
Amit Weisbord 3a8ff9bdd2
Fix broken url 2022-09-27 15:22:13 +03:00
Amit Weisbord 7b109240d2
Clarified collection in slice definition
Noticed the slice definition in the first paragraph relies on the reader recalling:
* what collections are
* that the reference page ended stating slices are a kind of reference

I think the first paragraph should be more clear to someone who lands on it and isn't reading the rest of the documentation ATM.
2022-09-27 10:14:41 +03:00
Víctor Hernández 3ebc3b285f
Update ch02-00-guessing-game-tutorial.md
The example code converts the input into a whole number. Replace the text "convert the String the program reads as input into a real number type" to "an actual number type" as the word real might be understood as one of the number categories instead as a synonym to "actual".
2022-09-01 14:22:21 +02:00
Alex Gotsis 6c63c46817 Improve awkward phrasing around the kinds of closures 2022-08-05 00:56:52 -07:00
JirCep 15616bc09b `expect` is not used multitude times by this chapter 2022-08-03 22:14:44 +02:00
Sanjyoti b260469985
Edit on line no. 153.
Edit on line no. 153. 

The adding of pub keyword to mod hosting and fn add_to_waitlist enables us to use the absolute and relative paths in the fn eat_at_restaurant according to the code specified in listing 7-7.
2022-07-27 20:10:36 +05:30
125 changed files with 548 additions and 482 deletions

View File

@ -2,7 +2,7 @@
name = "rust-book"
version = "0.0.1"
description = "The Rust Book"
edition = "2018"
edition = "2021"
[[bin]]
name = "concat_chapters"

View File

@ -25,7 +25,7 @@ fn main() {
// ANCHOR_END: expect
// ANCHOR: print_guess
println!("You guessed: {guess}");
println!("You guessed: {}", guess);
// ANCHOR_END: print_guess
}
// ANCHOR: all

View File

@ -6,4 +6,4 @@ fn main() {
// do stuff with s
} // this scope is now over, and s is no longer valid
// ANCHOR_END: here
}
}

View File

@ -14,10 +14,10 @@ fn main() {
// special happens.
fn takes_ownership(some_string: String) { // some_string comes into scope
println!("{}", some_string);
println!("{some_string}");
} // Here, some_string goes out of scope and `drop` is called. The backing
// memory is freed.
fn makes_copy(some_integer: i32) { // some_integer comes into scope
println!("{}", some_integer);
println!("{some_integer}");
} // Here, some_integer goes out of scope. Nothing special happens.

View File

@ -3,7 +3,7 @@ fn main() {
let (s2, len) = calculate_length(s1);
println!("The length of '{}' is {}.", s2, len);
println!("The length of '{s2}' is {len}.");
}
fn calculate_length(s: String) -> (String, usize) {

View File

@ -4,6 +4,6 @@ fn main() {
s.push_str(", world!"); // push_str() appends a literal to a String
println!("{}", s); // This will print `hello, world!`
// ANCHOR_END: here
println!("{s}"); // This will print `hello, world!`
// ANCHOR_END: here
}

View File

@ -3,6 +3,6 @@ fn main() {
let s1 = String::from("hello");
let s2 = s1;
println!("{}, world!", s1);
println!("{s1}, world!");
// ANCHOR_END: here
}

View File

@ -3,6 +3,6 @@ fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
println!("s1 = {s1}, s2 = {s2}");
// ANCHOR_END: here
}

View File

@ -3,6 +3,6 @@ fn main() {
let x = 5;
let y = x;
println!("x = {}, y = {}", x, y);
println!("x = {x}, y = {y}");
// ANCHOR_END: here
}

View File

@ -6,7 +6,7 @@ fn main() {
let len = calculate_length(&s1);
// ANCHOR_END: here
println!("The length of '{}' is {}.", s1, len);
println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: &String) -> usize {

View File

@ -3,7 +3,7 @@ fn main() {
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
println!("The length of '{s1}' is {len}.");
}
// ANCHOR: here

View File

@ -4,10 +4,10 @@ fn main() {
let r1 = &s; // no problem
let r2 = &s; // no problem
println!("{} and {}", r1, r2);
println!("{r1} and {r2}");
// variables r1 and r2 will not be used after this point
let r3 = &mut s; // no problem
println!("{}", r3);
println!("{r3}");
// ANCHOR_END: here
}

View File

@ -18,6 +18,6 @@ fn main() {
s.clear(); // error!
println!("the first word is: {}", word);
println!("the first word is: {word}");
}
// ANCHOR_END: here

View File

@ -10,5 +10,5 @@ fn main() {
height: 50,
};
println!("rect1 is {:?}", rect1);
println!("rect1 is {rect1:?}");
}

View File

@ -10,5 +10,5 @@ fn main() {
height: 50,
};
println!("rect1 is {:#?}", rect1);
println!("rect1 is {rect1:#?}");
}

View File

@ -2,7 +2,7 @@ fn main() {
// ANCHOR: here
let config_max = Some(3u8);
match config_max {
Some(max) => println!("The maximum is configured to be {}", max),
Some(max) => println!("The maximum is configured to be {max}"),
_ => (),
}
// ANCHOR_END: here

View File

@ -19,7 +19,7 @@ fn value_in_cents(coin: Coin) -> u8 {
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
println!("State quarter from {state:?}!");
25
}
}

View File

@ -2,7 +2,7 @@ fn main() {
// ANCHOR: here
let config_max = Some(3u8);
if let Some(max) = config_max {
println!("The maximum is configured to be {}", max);
println!("The maximum is configured to be {max}");
}
// ANCHOR_END: here
}

View File

@ -17,7 +17,7 @@ fn main() {
// ANCHOR: here
let mut count = 0;
match coin {
Coin::Quarter(state) => println!("State quarter from {:?}!", state),
Coin::Quarter(state) => println!("State quarter from {state:?}!"),
_ => count += 1,
}
// ANCHOR_END: here

View File

@ -17,7 +17,7 @@ fn main() {
// ANCHOR: here
let mut count = 0;
if let Coin::Quarter(state) = coin {
println!("State quarter from {:?}!", state);
println!("State quarter from {state:?}!");
} else {
count += 1;
}

View File

@ -4,5 +4,5 @@ pub mod garden;
fn main() {
let plant = Asparagus {};
println!("I'm growing {:?}!", plant);
println!("I'm growing {plant:?}!");
}

View File

@ -7,6 +7,6 @@ fn main() {
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Blue"), 25);
println!("{:?}", scores);
println!("{scores:?}");
// ANCHOR_END: here
}

View File

@ -8,6 +8,6 @@ fn main() {
scores.entry(String::from("Yellow")).or_insert(50);
scores.entry(String::from("Blue")).or_insert(50);
println!("{:?}", scores);
println!("{scores:?}");
// ANCHOR_END: here
}

View File

@ -11,6 +11,6 @@ fn main() {
*count += 1;
}
println!("{:?}", map);
println!("{map:?}");
// ANCHOR_END: here
}

View File

@ -5,6 +5,6 @@ fn main() {
let greeting_file = match greeting_file_result {
Ok(file) => file,
Err(error) => panic!("Problem opening the file: {:?}", error),
Err(error) => panic!("Problem opening the file: {error:?}"),
};
}

View File

@ -9,10 +9,10 @@ fn main() {
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Problem creating the file: {:?}", e),
Err(e) => panic!("Problem creating the file: {e:?}"),
},
other_error => {
panic!("Problem opening the file: {:?}", other_error);
panic!("Problem opening the file: {other_error:?}");
}
},
};

View File

@ -10,7 +10,7 @@ fn main() {
}
}
println!("The largest number is {}", largest);
println!("The largest number is {largest}");
// ANCHOR_END: here
assert_eq!(*largest, 100);
// ANCHOR: here

View File

@ -9,7 +9,7 @@ fn main() {
}
}
println!("The largest number is {}", largest);
println!("The largest number is {largest}");
let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];
@ -21,5 +21,5 @@ fn main() {
}
}
println!("The largest number is {}", largest);
println!("The largest number is {largest}");
}

View File

@ -15,7 +15,7 @@ fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
println!("The largest number is {}", result);
println!("The largest number is {result}");
// ANCHOR_END: here
assert_eq!(*result, 100);
// ANCHOR: here
@ -23,7 +23,7 @@ fn main() {
let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];
let result = largest(&number_list);
println!("The largest number is {}", result);
println!("The largest number is {result}");
// ANCHOR_END: here
assert_eq!(*result, 6000);
// ANCHOR: here

View File

@ -27,7 +27,7 @@ fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest_i32(&number_list);
println!("The largest number is {}", result);
println!("The largest number is {result}");
// ANCHOR_END: here
assert_eq!(*result, 100);
// ANCHOR: here
@ -35,7 +35,7 @@ fn main() {
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest_char(&char_list);
println!("The largest char is {}", result);
println!("The largest char is {result}");
// ANCHOR_END: here
assert_eq!(*result, 'y');
// ANCHOR: here

View File

@ -14,10 +14,10 @@ fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
println!("The largest number is {}", result);
println!("The largest number is {result}");
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&char_list);
println!("The largest char is {}", result);
println!("The largest char is {result}");
}

View File

@ -6,5 +6,5 @@ fn main() {
r = &x;
}
println!("r: {}", r);
println!("r: {r}");
}

View File

@ -6,5 +6,5 @@ fn main() {
r = &x; // | |
} // -+ |
// |
println!("r: {}", r); // |
println!("r: {r}"); // |
} // ---------+

View File

@ -3,6 +3,6 @@ fn main() {
// |
let r = &x; // --+-- 'a |
// | |
println!("r: {}", r); // | |
println!("r: {r}"); // | |
// --+ |
} // ----------+

View File

@ -3,5 +3,5 @@ fn main() {
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is {}", result);
println!("The longest string is {result}");
}

View File

@ -3,7 +3,7 @@ fn main() {
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is {}", result);
println!("The longest string is {result}");
}
// ANCHOR: here

View File

@ -3,7 +3,7 @@ fn main() {
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is {}", result);
println!("The longest string is {result}");
}
// ANCHOR: here

View File

@ -5,7 +5,7 @@ fn main() {
{
let string2 = String::from("xyz");
let result = longest(string1.as_str(), string2.as_str());
println!("The longest string is {}", result);
println!("The longest string is {result}");
}
}
// ANCHOR_END: here

View File

@ -9,8 +9,8 @@ error[E0597]: `string2` does not live long enough
| ^^^^^^^ borrowed value does not live long enough
7 | }
| - `string2` dropped here while still borrowed
8 | println!("The longest string is {}", result);
| ------ borrow later used here
8 | println!("The longest string is {result}");
| ------ borrow later used here
For more information about this error, try `rustc --explain E0597`.
error: could not compile `chapter10` (bin "chapter10") due to 1 previous error

View File

@ -6,7 +6,7 @@ fn main() {
let string2 = String::from("xyz");
result = longest(string1.as_str(), string2.as_str());
}
println!("The longest string is {}", result);
println!("The longest string is {result}");
}
// ANCHOR_END: here

View File

@ -3,7 +3,7 @@ fn main() {
let string2 = "efghijklmnopqrstuvwxyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is {}", result);
println!("The longest string is {result}");
}
// ANCHOR: here

View File

@ -3,7 +3,7 @@ fn main() {
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is {}", result);
println!("The longest string is {result}");
}
// ANCHOR: here

View File

@ -13,7 +13,7 @@ impl<'a> ImportantExcerpt<'a> {
// ANCHOR: 3rd
impl<'a> ImportantExcerpt<'a> {
fn announce_and_return_part(&self, announcement: &str) -> &str {
println!("Attention please: {}", announcement);
println!("Attention please: {announcement}");
self.part
}
}

View File

@ -7,7 +7,7 @@ fn main() {
string2,
"Today is someone's birthday!",
);
println!("The longest string is {}", result);
println!("The longest string is {result}");
}
// ANCHOR: here
@ -21,7 +21,7 @@ fn longest_with_an_announcement<'a, T>(
where
T: Display,
{
println!("Announcement! {}", ann);
println!("Announcement! {ann}");
if x.len() > y.len() {
x
} else {

View File

@ -1,5 +1,5 @@
fn prints_and_returns_10(a: i32) -> i32 {
println!("I got the value {}", a);
println!("I got the value {a}");
10
}

View File

@ -1,5 +1,5 @@
pub fn greeting(name: &str) -> String {
format!("Hello {}!", name)
format!("Hello {name}!")
}
#[cfg(test)]

View File

@ -1,5 +1,5 @@
pub fn prints_and_returns_10(a: i32) -> i32 {
println!("I got the value {}", a);
println!("I got the value {a}");
10
}

View File

@ -6,6 +6,6 @@ fn main() {
let query = &args[1];
let file_path = &args[2];
println!("Searching for {}", query);
println!("In file {}", file_path);
println!("Searching for {query}");
println!("In file {file_path}");
}

View File

@ -6,6 +6,6 @@ fn main() {
let query = &args[1];
let file_path = &args[2];
println!("Searching for {}", query);
println!("In file {}", file_path);
println!("Searching for {query}");
println!("In file {file_path}");
}

View File

@ -10,9 +10,9 @@ fn main() {
let query = &args[1];
let file_path = &args[2];
println!("Searching for {}", query);
println!("Searching for {query}");
// ANCHOR: here
println!("In file {}", file_path);
println!("In file {file_path}");
let contents = fs::read_to_string(file_path)
.expect("Should have been able to read the file");

View File

@ -10,8 +10,8 @@ fn main() {
// --snip--
// ANCHOR_END: here
println!("Searching for {}", query);
println!("In file {}", file_path);
println!("Searching for {query}");
println!("In file {file_path}");
let contents = fs::read_to_string(file_path)
.expect("Should have been able to read the file");

View File

@ -1,10 +1,10 @@
fn main() {
let list = vec![1, 2, 3];
println!("Before defining closure: {:?}", list);
println!("Before defining closure: {list:?}");
let only_borrows = || println!("From closure: {:?}", list);
let only_borrows = || println!("From closure: {list:?}");
println!("Before calling closure: {:?}", list);
println!("Before calling closure: {list:?}");
only_borrows();
println!("After calling closure: {:?}", list);
println!("After calling closure: {list:?}");
}

View File

@ -1,9 +1,9 @@
fn main() {
let mut list = vec![1, 2, 3];
println!("Before defining closure: {:?}", list);
println!("Before defining closure: {list:?}");
let mut borrows_mutably = || list.push(7);
borrows_mutably();
println!("After calling closure: {:?}", list);
println!("After calling closure: {list:?}");
}

View File

@ -2,9 +2,9 @@ use std::thread;
fn main() {
let list = vec![1, 2, 3];
println!("Before defining closure: {:?}", list);
println!("Before defining closure: {list:?}");
thread::spawn(move || println!("From thread: {:?}", list))
thread::spawn(move || println!("From thread: {list:?}"))
.join()
.unwrap();
}

View File

@ -12,5 +12,5 @@ fn main() {
];
list.sort_by_key(|r| r.width);
println!("{:#?}", list);
println!("{list:#?}");
}

View File

@ -18,5 +18,5 @@ fn main() {
sort_operations.push(value);
r.width
});
println!("{:#?}", list);
println!("{list:#?}");
}

View File

@ -16,5 +16,5 @@ fn main() {
num_sort_operations += 1;
r.width
});
println!("{:#?}, sorted in {num_sort_operations} operations", list);
println!("{list:#?}, sorted in {num_sort_operations} operations");
}

View File

@ -5,7 +5,7 @@ fn main() {
let v1_iter = v1.iter();
for val in v1_iter {
println!("Got: {}", val);
println!("Got: {val}");
}
// ANCHOR_END: here
}

View File

@ -1,4 +1,4 @@
fn main() {
let b = Box::new(5);
println!("b = {}", b);
println!("b = {b}");
}

View File

@ -18,7 +18,7 @@ fn main() {
*value.borrow_mut() += 10;
println!("a after = {:?}", a);
println!("b after = {:?}", b);
println!("c after = {:?}", c);
println!("a after = {a:?}");
println!("b after = {b:?}");
println!("c after = {c:?}");
}

View File

@ -4,13 +4,13 @@ use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
println!("hi number {i} from the main thread!");
thread::sleep(Duration::from_millis(1));
}
}

View File

@ -4,13 +4,13 @@ use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
println!("hi number {i} from the main thread!");
thread::sleep(Duration::from_millis(1));
}

View File

@ -5,15 +5,15 @@ error[E0373]: closure may outlive the current function, but it borrows `v`, whic
|
6 | let handle = thread::spawn(|| {
| ^^ may outlive borrowed value `v`
7 | println!("Here's a vector: {:?}", v);
| - `v` is borrowed here
7 | println!("Here's a vector: {v:?}");
| - `v` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src/main.rs:6:18
|
6 | let handle = thread::spawn(|| {
| __________________^
7 | | println!("Here's a vector: {:?}", v);
7 | | println!("Here's a vector: {v:?}");
8 | | });
| |______^
help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword

View File

@ -4,7 +4,7 @@ fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(|| {
println!("Here's a vector: {:?}", v);
println!("Here's a vector: {v:?}");
});
handle.join().unwrap();

View File

@ -4,7 +4,7 @@ fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(|| {
println!("Here's a vector: {:?}", v);
println!("Here's a vector: {v:?}");
});
drop(v); // oh no!

View File

@ -4,7 +4,7 @@ fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("Here's a vector: {:?}", v);
println!("Here's a vector: {v:?}");
});
handle.join().unwrap();

View File

@ -10,5 +10,5 @@ fn main() {
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
println!("Got: {received}");
}

View File

@ -7,8 +7,8 @@ error[E0382]: borrow of moved value: `val`
| --- move occurs because `val` has type `String`, which does not implement the `Copy` trait
9 | tx.send(val).unwrap();
| --- value moved here
10 | println!("val is {}", val);
| ^^^ value borrowed here after move
10 | println!("val is {val}");
| ^^^ value borrowed here after move
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable

View File

@ -7,9 +7,9 @@ fn main() {
thread::spawn(move || {
let val = String::from("hi");
tx.send(val).unwrap();
println!("val is {}", val);
println!("val is {val}");
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
println!("Got: {received}");
}

View File

@ -20,6 +20,6 @@ fn main() {
});
for received in rx {
println!("Got: {}", received);
println!("Got: {received}");
}
}

View File

@ -38,7 +38,7 @@ fn main() {
});
for received in rx {
println!("Got: {}", received);
println!("Got: {received}");
}
// --snip--

View File

@ -8,5 +8,5 @@ fn main() {
*num = 6;
}
println!("m = {:?}", m);
println!("m = {m:?}");
}

View File

@ -4,7 +4,7 @@ use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});
@ -12,7 +12,7 @@ fn main() {
handle.join().unwrap();
for i in 1..5 {
println!("hi number {} from the main thread!", i);
println!("hi number {i} from the main thread!");
thread::sleep(Duration::from_millis(1));
}
}

View File

@ -8,8 +8,8 @@ error[E0382]: use of moved value: `v`
5 |
6 | let handle = thread::spawn(move || {
| ------- value moved into closure here
7 | println!("Here's a vector: {:?}", v);
| - variable moved due to use in closure
7 | println!("Here's a vector: {v:?}");
| - variable moved due to use in closure
...
10 | drop(v); // oh no!
| ^ value used here after move

View File

@ -4,7 +4,7 @@ fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("Here's a vector: {:?}", v);
println!("Here's a vector: {v:?}");
});
drop(v); // oh no!

View File

@ -7,7 +7,7 @@ fn main() {
stack.push(3);
while let Some(top) = stack.pop() {
println!("{}", top);
println!("{top}");
}
// ANCHOR_END: here
}

View File

@ -3,7 +3,7 @@ fn main() {
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
println!("{} is at index {}", value, index);
println!("{value} is at index {index}");
}
// ANCHOR_END: here
}

View File

@ -1,5 +1,5 @@
fn print_coordinates(&(x, y): &(i32, i32)) {
println!("Current location: ({}, {})", x, y);
println!("Current location: ({x}, {y})");
}
fn main() {

View File

@ -2,7 +2,7 @@ fn main() {
let some_option_value: Option<i32> = None;
// ANCHOR: here
if let Some(x) = some_option_value {
println!("{}", x);
println!("{x}");
}
// ANCHOR_END: here
}

View File

@ -1,7 +1,7 @@
fn main() {
// ANCHOR: here
if let x = 5 {
println!("{}", x);
println!("{x}");
};
// ANCHOR_END: here
}

View File

@ -6,9 +6,9 @@ fn main() {
match x {
Some(50) => println!("Got 50"),
Some(y) => println!("Matched, y = {y}"),
_ => println!("Default case, x = {:?}", x),
_ => println!("Default case, x = {x:?}"),
}
println!("at the end: x = {:?}, y = {y}", x);
println!("at the end: x = {x:?}, y = {y}");
// ANCHOR_END: here
}

View File

@ -19,7 +19,7 @@ fn main() {
println!("Text message: {text}");
}
Message::ChangeColor(r, g, b) => {
println!("Change the color to red {r}, green {g}, and blue {b}",)
println!("Change the color to red {r}, green {g}, and blue {b}")
}
}
}

View File

@ -1,5 +1,5 @@
fn foo(_: i32, y: i32) {
println!("This code only uses the y parameter: {}", y);
println!("This code only uses the y parameter: {y}");
}
fn main() {

View File

@ -12,6 +12,6 @@ fn main() {
}
}
println!("setting is {:?}", setting_value);
println!("setting is {setting_value:?}");
// ANCHOR_END: here
}

View File

@ -6,6 +6,6 @@ fn main() {
println!("found a string");
}
println!("{:?}", s);
println!("{s:?}");
// ANCHOR_END: here
}

View File

@ -6,6 +6,6 @@ fn main() {
println!("found a string");
}
println!("{:?}", s);
println!("{s:?}");
// ANCHOR_END: here
}

View File

@ -9,7 +9,7 @@ fn main() {
let origin = Point { x: 0, y: 0, z: 0 };
match origin {
Point { x, .. } => println!("x is {}", x),
Point { x, .. } => println!("x is {x}"),
}
// ANCHOR_END: here
}

View File

@ -3,7 +3,7 @@ fn main() {
match numbers {
(.., second, ..) => {
println!("Some numbers: {}", second)
println!("Some numbers: {second}")
},
}
}

View File

@ -3,8 +3,8 @@ fn main() {
let num = Some(4);
match num {
Some(x) if x % 2 == 0 => println!("The number {} is even", x),
Some(x) => println!("The number {} is odd", x),
Some(x) if x % 2 == 0 => println!("The number {x} is even"),
Some(x) => println!("The number {x} is odd"),
None => (),
}
// ANCHOR_END: here

View File

@ -5,8 +5,8 @@ fn main() {
match x {
Some(50) => println!("Got 50"),
Some(n) if n == y => println!("Matched, n = {n}"),
_ => println!("Default case, x = {:?}", x),
_ => println!("Default case, x = {x:?}"),
}
println!("at the end: x = {:?}, y = {y}", x);
println!("at the end: x = {x:?}, y = {y}");
}

View File

@ -9,11 +9,11 @@ fn main() {
match msg {
Message::Hello {
id: id_variable @ 3..=7,
} => println!("Found an id in range: {}", id_variable),
} => println!("Found an id in range: {id_variable}"),
Message::Hello { id: 10..=12 } => {
println!("Found an id in another range")
}
Message::Hello { id } => println!("Found some other id: {}", id),
Message::Hello { id } => println!("Found some other id: {id}"),
}
// ANCHOR_END: here
}

View File

@ -1,5 +1,5 @@
static HELLO_WORLD: &str = "Hello, world!";
fn main() {
println!("name is: {}", HELLO_WORLD);
println!("name is: {HELLO_WORLD}");
}

View File

@ -10,6 +10,6 @@ fn main() {
add_to_count(3);
unsafe {
println!("COUNTER: {}", COUNTER);
println!("COUNTER: {COUNTER}");
}
}

View File

@ -7,7 +7,7 @@ trait OutlinePrint: fmt::Display {
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {} *", output);
println!("* {output} *");
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}

View File

@ -10,5 +10,5 @@ impl fmt::Display for Wrapper {
fn main() {
let w = Wrapper(vec![String::from("hello"), String::from("world")]);
println!("w = {}", w);
println!("w = {w}");
}

View File

@ -9,5 +9,5 @@ fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
fn main() {
let answer = do_twice(add_one, 5);
println!("The answer is: {}", answer);
println!("The answer is: {answer}");
}

View File

@ -6,7 +6,7 @@ trait OutlinePrint: fmt::Display {
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {} *", output);
println!("* {output} *");
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}

View File

@ -4,7 +4,7 @@ trait OutlinePrint: fmt::Display {
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {} *", output);
println!("* {output} *");
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}

View File

@ -21,5 +21,5 @@ fn handle_connection(mut stream: TcpStream) {
.take_while(|line| !line.is_empty())
.collect();
println!("Request: {:#?}", http_request);
println!("Request: {http_request:#?}");
}

View File

@ -20,7 +20,7 @@ optionally one library crate. As a package grows, you can extract parts into
separate crates that become external dependencies. This chapter covers all
these techniques. For very large projects comprising a set of interrelated
packages that evolve together, Cargo provides *workspaces*, which well cover
in “Cargo Workspaces” on page XX.
in the “Cargo Workspaces” section in Chapter 14.
Well also discuss encapsulating implementation details, which lets you reuse
code at a higher level: once youve implemented an operation, other code can
@ -43,11 +43,11 @@ organization, including which details are exposed, which details are private,
and what names are in each scope in your programs. These features, sometimes
collectively referred to as the *module system*, include:
* **Packages **: A Cargo feature that lets you build, test, and share crates
* **Crates**: A tree of modules that produces a library or executable
* **Modules and use**: Let you control the organization, scope, and privacy of
paths
* **Paths **: A way of naming an item, such as a struct, function, or module
* **Packages:** A Cargo feature that lets you build, test, and share crates
* **Crates:** A tree of modules that produces a library or executable
* **Modules** and **use:** Let you control the organization, scope, and
privacy of paths
* **Paths:** A way of naming an item, such as a struct, function, or module
In this chapter, well cover all these features, discuss how they interact, and
explain how to use them to manage scope. By the end, you should have a solid
@ -59,35 +59,36 @@ The first parts of the module system well cover are packages and crates.
A *crate* is the smallest amount of code that the Rust compiler considers at a
time. Even if you run `rustc` rather than `cargo` and pass a single source code
file (as we did all the way back in “Writing and Running a Rust Program” on
page XX), the compiler considers that file to be a crate. Crates can contain
modules, and the modules may be defined in other files that get compiled with
the crate, as well see in the coming sections.
file (as we did all the way back in the “Writing and Running a Rust Program”
section of Chapter 1), the compiler considers that file to be a crate. Crates
can contain modules, and the modules may be defined in other files that get
compiled with the crate, as well see in the coming sections.
A crate can come in one of two forms: a binary crate or a library crate.
*Binary crates* are programs you can compile to an executable that you can run,
such as a command line program or a server. Each must have a function called
such as a command-line program or a server. Each must have a function called
`main` that defines what happens when the executable runs. All the crates weve
created so far have been binary crates.
*Library crates* dont have a `main` function, and they dont compile to an
executable. Instead, they define functionality intended to be shared with
multiple projects. For example, the `rand` crate we used in Chapter 2 provides
functionality that generates random numbers. Most of the time when Rustaceans
say “crate,” they mean library crate, and they use “crate” interchangeably with
the general programming concept of a “library.
multiple projects. For example, the `rand` crate we used in Chapter
2 provides functionality that generates random numbers.
Most of the time when Rustaceans say “crate”, they mean library crate, and they
use “crate” interchangeably with the general programming concept of a “library".
The *crate root* is a source file that the Rust compiler starts from and makes
up the root module of your crate (well explain modules in depth in “Defining
Modules to Control Scope and Privacy” on page XX).
up the root module of your crate (well explain modules in depth in the
“Defining Modules to Control Scope and Privacy”
section).
A *package* is a bundle of one or more crates that provides a set of
functionality. A package contains a *Cargo.toml* file that describes how to
build those crates. Cargo is actually a package that contains the binary crate
for the command line tool youve been using to build your code. The Cargo
for the command-line tool youve been using to build your code. The Cargo
package also contains a library crate that the binary crate depends on. Other
projects can depend on the Cargo library crate to use the same logic the Cargo
command line tool uses.
command-line tool uses.
A crate can come in one of two forms: a binary crate or a library crate. A
package can contain as many binary crates as you like, but at most only one
@ -123,94 +124,6 @@ and *src/lib.rs*, it has two crates: a binary and a library, both with the same
name as the package. A package can have multiple binary crates by placing files
in the *src/bin* directory: each file will be a separate binary crate.
> ### Modules Cheat Sheet
>
> Before we get to the details of modules and paths, here we provide a quick
reference on how modules, paths, the `use` keyword, and the `pub` keyword work
in the compiler, and how most developers organize their code. Well be going
through examples of each of these rules throughout this chapter, but this is a
great place to refer to as a reminder of how modules work.
>
> * **Start from the crate root**: When compiling a crate, the compiler first
looks in the crate root file (usually *src/lib.rs* for a library crate or
*src/main.rs* for a binary crate) for code to compile.
> * **Declaring modules**: In the crate root file, you can declare new modules;
say you declare a “garden” module with `mod garden;`. The compiler will look
for the modules code in these places:
>
> * Inline, within curly brackets that replace the semicolon following `mod
garden`
> * In the file *src/garden.rs.*
> * In the file *src/garden/mod.rs*
> * **Declaring submodules**: In any file other than the crate root, you can
declare submodules. For example, you might declare `mod vegetables;` in
*src/garden.rs*. The compiler will look for the submodules code within the
directory named for the parent module in these places:
>
> * Inline, directly following `mod vegetables`, within curly brackets instead
of the semicolon
> * In the file *src/garden/vegetables.rs*
> * In the file *src/garden/vegetables/mod.rs*
> * **Paths to code in modules**: Once a module is part of your crate, you can
refer to code in that module from anywhere else in that same crate, as long as
the privacy rules allow, using the path to the code. For example, an
`Asparagus` type in the garden vegetables module would be found at
`crate::garden::vegetables::Asparagus`.
> * **Private vs. public**: Code within a module is private from its parent
modules by default. To make a module public, declare it with `pub mod` instead
of `mod`. To make items within a public module public as well, use `pub` before
their declarations.
> * **The use keyword**: Within a scope, the `use` keyword creates shortcuts to
items to reduce repetition of long paths. In any scope that can refer to
`crate::garden::vegetables::Asparagus`, you can create a shortcut with `use
crate::garden::vegetables::Asparagus;` and from then on you only need to write
`Asparagus` to make use of that type in the scope.
>
> Here, we create a binary crate named `backyard` that illustrates these rules.
The crates directory, also named `backyard`, contains these files and
directories:
>
> ```
> backyard
> ├── Cargo.lock
> ├── Cargo.toml
> └── src
> ├── garden
> │ └── vegetables.rs
> ├── garden.rs
> └── main.rs
> ```
>
> The crate root file in this case is *src/main.rs*, and it contains:
>
> ```
> use crate::garden::vegetables::Asparagus;
>
> pub mod garden;
>
> fn main() {
> let plant = Asparagus {};
> println!("I'm growing {:?}!", plant);
> }
> ```
>
> The `pub mod garden;` line tells the compiler to include the code it finds in
*src/garden.rs*, which is:
>
> ```
> pub mod vegetables;
> ```
>
> Here, `pub mod vegetables;` means the code in *src/garden/vegetables.rs* is
included too. That code is:
>
> ```
> #[derive(Debug)]
> pub struct Asparagus {}
> ```
>
> Now lets get into the details of these rules and demonstrate them in action!
## Defining Modules to Control Scope and Privacy
In this section, well talk about modules and other parts of the module system,
@ -218,6 +131,98 @@ namely *paths*, which allow you to name items; the `use` keyword that brings a
path into scope; and the `pub` keyword to make items public. Well also discuss
the `as` keyword, external packages, and the glob operator.
### Modules Cheat Sheet
Before we get to the details of modules and paths, here we provide a quick
reference on how modules, paths, the `use` keyword, and the `pub` keyword work
in the compiler, and how most developers organize their code. Well be going
through examples of each of these rules throughout this chapter, but this is a
great place to refer to as a reminder of how modules work.
- **Start from the crate root**: When compiling a crate, the compiler first
looks in the crate root file (usually *src/lib.rs* for a library crate or
*src/main.rs* for a binary crate) for code to compile.
- **Declaring modules**: In the crate root file, you can declare new modules;
say you declare a “garden” module with `mod garden;`. The compiler will look
for the modules code in these places:
- Inline, within curly brackets that replace the semicolon following `mod
garden`
- In the file *src/garden.rs*
- In the file *src/garden/mod.rs*
- **Declaring submodules**: In any file other than the crate root, you can
declare submodules. For example, you might declare `mod vegetables;` in
*src/garden.rs*. The compiler will look for the submodules code within the
directory named for the parent module in these places:
- Inline, directly following `mod vegetables`, within curly brackets instead
of the semicolon
- In the file *src/garden/vegetables.rs*
- In the file *src/garden/vegetables/mod.rs*
- **Paths to code in modules**: Once a module is part of your crate, you can
refer to code in that module from anywhere else in that same crate, as long
as the privacy rules allow, using the path to the code. For example, an
`Asparagus` type in the garden vegetables module would be found at
`crate::garden::vegetables::Asparagus`.
- **Private vs. public**: Code within a module is private from its parent
modules by default. To make a module public, declare it with `pub mod`
instead of `mod`. To make items within a public module public as well, use
`pub` before their declarations.
- **The `use` keyword**: Within a scope, the `use` keyword creates shortcuts to
items to reduce repetition of long paths. In any scope that can refer to
`crate::garden::vegetables::Asparagus`, you can create a shortcut with `use
crate::garden::vegetables::Asparagus;` and from then on you only need to
write `Asparagus` to make use of that type in the scope.
Here, we create a binary crate named `backyard` that illustrates these rules.
The crates directory, also named `backyard`, contains these files and
directories:
```
backyard
├── Cargo.lock
├── Cargo.toml
└── src
├── garden
│   └── vegetables.rs
├── garden.rs
└── main.rs
```
The crate root file in this case is *src/main.rs*, and it contains:
Filename: src/main.rs
```
use crate::garden::vegetables::Asparagus;
pub mod garden;
fn main() {
let plant = Asparagus {};
println!("I'm growing {:?}!", plant);
}
```
The `pub mod garden;` line tells the compiler to include the code it finds in
*src/garden.rs*, which is:
Filename: src/garden.rs
```
pub mod vegetables;
```
Here, `pub mod vegetables;` means the code in *src/garden/vegetables.rs* is
included too. That code is:
```
#[derive(Debug)]
pub struct Asparagus {}
```
Now lets get into the details of these rules and demonstrate them in action!
### Grouping Related Code in Modules
*Modules* let us organize code within a crate for readability and easy reuse.
Modules also allow us to control the *privacy* of items because code within a
module is private by default. Private items are internal implementation details
@ -263,8 +268,8 @@ mod front_of_house {
}
```
Listing 7-1: A `front_of_house` module containing other modules that then
contain functions
Listing 7-1: A `front_of_house` module containing other
modules that then contain functions
We define a module with the `mod` keyword followed by the name of the module
(in this case, `front_of_house`). The body of the module then goes inside curly
@ -298,7 +303,8 @@ crate
└── take_payment
```
Listing 7-2: The module tree for the code in Listing 7-1
Listing 7-2: The module tree for the code in Listing
7-1
This tree shows how some of the modules nest inside other modules; for example,
`hosting` nests inside `front_of_house`. The tree also shows that some modules
@ -321,18 +327,19 @@ know its path.
A path can take two forms:
* An *absolute path* is the full path starting from a crate root; for code from
an external crate, the absolute path begins with the crate name, and for code
from the current crate, it starts with the literal `crate`.
* An *absolute path* is the full path starting from a crate root; for code
from an external crate, the absolute path begins with the crate name, and for
code from the current crate, it starts with the literal `crate`.
* A *relative path* starts from the current module and uses `self`, `super`, or
an identifier in the current module.
an identifier in the current module.
Both absolute and relative paths are followed by one or more identifiers
separated by double colons (`::`).
Returning to Listing 7-1, say we want to call the `add_to_waitlist` function.
This is the same as asking: whats the path of the `add_to_waitlist` function?
Listing 7-3 contains Listing 7-1 with some of the modules and functions removed.
Listing 7-3 contains Listing 7-1 with some of the modules and functions
removed.
Well show two ways to call the `add_to_waitlist` function from a new function,
`eat_at_restaurant`, defined in the crate root. These paths are correct, but
@ -340,8 +347,8 @@ theres another problem remaining that will prevent this example from compilin
as is. Well explain why in a bit.
The `eat_at_restaurant` function is part of our library crates public API, so
we mark it with the `pub` keyword. In “Exposing Paths with the pub Keyword” on
page XX, well go into more detail about `pub`.
we mark it with the `pub` keyword. In the “Exposing Paths with the `pub`
Keyword” section, well go into more detail about `pub`.
Filename: src/lib.rs
@ -361,8 +368,8 @@ pub fn eat_at_restaurant() {
}
```
Listing 7-3: Calling the `add_to_waitlist` function using absolute and relative
paths
Listing 7-3: Calling the `add_to_waitlist` function using
absolute and relative paths
The first time we call the `add_to_waitlist` function in `eat_at_restaurant`,
we use an absolute path. The `add_to_waitlist` function is defined in the same
@ -403,7 +410,9 @@ error[E0603]: module `hosting` is private
--> src/lib.rs:9:28
|
9 | crate::front_of_house::hosting::add_to_waitlist();
| ^^^^^^^ private module
| ^^^^^^^ --------------- function `add_to_waitlist` is not publicly re-exported
| |
| private module
|
note: the module `hosting` is defined here
--> src/lib.rs:2:5
@ -415,16 +424,22 @@ error[E0603]: module `hosting` is private
--> src/lib.rs:12:21
|
12 | front_of_house::hosting::add_to_waitlist();
| ^^^^^^^ private module
| ^^^^^^^ --------------- function `add_to_waitlist` is not publicly re-exported
| |
| private module
|
note: the module `hosting` is defined here
--> src/lib.rs:2:5
|
2 | mod hosting {
| ^^^^^^^^^^^
For more information about this error, try `rustc --explain E0603`.
error: could not compile `restaurant` (lib) due to 2 previous errors
```
Listing 7-4: Compiler errors from building the code in Listing 7-3
Listing 7-4: Compiler errors from building the code in
Listing 7-3
The error messages say that module `hosting` is private. In other words, we
have the correct paths for the `hosting` module and the `add_to_waitlist`
@ -447,7 +462,7 @@ inner code you can change without breaking outer code. However, Rust does give
you the option to expose inner parts of child modules code to outer ancestor
modules by using the `pub` keyword to make an item public.
### Exposing Paths with the pub Keyword
### Exposing Paths with the `pub` Keyword
Lets return to the error in Listing 7-4 that told us the `hosting` module is
private. We want the `eat_at_restaurant` function in the parent module to have
@ -463,11 +478,17 @@ mod front_of_house {
}
}
--snip--
pub fn eat_at_restaurant() {
// Absolute path
crate::front_of_house::hosting::add_to_waitlist();
// Relative path
front_of_house::hosting::add_to_waitlist();
}
```
Listing 7-5: Declaring the `hosting` module as `pub` to use it from
`eat_at_restaurant`
Listing 7-5: Declaring the `hosting` module as `pub` to
use it from `eat_at_restaurant`
Unfortunately, the code in Listing 7-5 still results in compiler errors, as
shown in Listing 7-6.
@ -498,9 +519,13 @@ note: the function `add_to_waitlist` is defined here
|
3 | fn add_to_waitlist() {}
| ^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0603`.
error: could not compile `restaurant` (lib) due to 2 previous errors
```
Listing 7-6: Compiler errors from building the code in Listing 7-5
Listing 7-6: Compiler errors from building the code in
Listing 7-5
What happened? Adding the `pub` keyword in front of `mod hosting` makes the
module public. With this change, if we can access `front_of_house`, we can
@ -527,11 +552,18 @@ mod front_of_house {
}
}
--snip--
pub fn eat_at_restaurant() {
// Absolute path
crate::front_of_house::hosting::add_to_waitlist();
// Relative path
front_of_house::hosting::add_to_waitlist();
}
```
Listing 7-7: Adding the `pub` keyword to `mod hosting` and `fn add_to_waitlist`
lets us call the function from `eat_at_restaurant`.
Listing 7-7: Adding the `pub` keyword to `mod hosting`
and `fn add_to_waitlist` lets us call the function from
`eat_at_restaurant`
Now the code will compile! To see why adding the `pub` keyword lets us use
these paths in `add_to_waitlist` with respect to the privacy rules, lets look
@ -559,31 +591,31 @@ If you plan on sharing your library crate so other projects can use your code,
your public API is your contract with users of your crate that determines how
they can interact with your code. There are many considerations around managing
changes to your public API to make it easier for people to depend on your
crate. These considerations are beyond the scope of this book; if youre
interested in this topic, see the Rust API Guidelines at
*https://rust-lang.github.io/api-guidelines*.
crate. These considerations are out of the scope of this book; if youre
interested in this topic, see The Rust API Guidelines at *https://rust-lang.github.io/api-guidelines/*.
> ### Best Practices for Packages with a Binary and a Library
> #### Best Practices for Packages with a Binary and a Library
>
> We mentioned that a package can contain both a *src/main.rs* binary crate
root as well as a *src/lib.rs* library crate root, and both crates will have
the package name by default. Typically, packages with this pattern of
containing both a library and a binary crate will have just enough code in the
binary crate to start an executable that calls code with the library crate.
This lets other projects benefit from the most functionality that the package
provides because the library crates code can be shared.
> root as well as a *src/lib.rs* library crate root, and both crates will have
> the package name by default. Typically, packages with this pattern of
> containing both a library and a binary crate will have just enough code in the
> binary crate to start an executable that calls code within the library crate.
> This lets other projects benefit from most of the functionality that the
> package provides because the library crates code can be shared.
>
> The module tree should be defined in *src/lib.rs*. Then, any public items can
be used in the binary crate by starting paths with the name of the package. The
binary crate becomes a user of the library crate just like a completely
external crate would use the library crate: it can only use the public API.
This helps you design a good API; not only are you the author, youre also a
client!
> be used in the binary crate by starting paths with the name of the package.
> The binary crate becomes a user of the library crate just like a completely
> external crate would use the library crate: it can only use the public API.
> This helps you design a good API; not only are you the author, youre also a
> client!
>
> In Chapter 12, well demonstrate this organizational practice with a command
line program that will contain both a binary crate and a library crate.
> In Chapter 12, well demonstrate this organizational
> practice with a command-line program that will contain both a binary crate
> and a library crate.
### Starting Relative Paths with super
### Starting Relative Paths with `super`
We can construct relative paths that begin in the parent module, rather than
the current module or the crate root, by using `super` at the start of the
@ -614,7 +646,8 @@ mod back_of_house {
}
```
Listing 7-8: Calling a function using a relative path starting with `super`
Listing 7-8: Calling a function using a relative path
starting with `super`
The `fix_incorrect_order` function is in the `back_of_house` module, so we can
use `super` to go to the parent module of `back_of_house`, which in this case
@ -664,14 +697,14 @@ pub fn eat_at_restaurant() {
meal.toast = String::from("Wheat");
println!("I'd like {} toast please", meal.toast);
// The next line won't compile if we uncomment it; we're not
// allowed to see or modify the seasonal fruit that comes
// with the meal
// The next line won't compile if we uncomment it; we're not allowed
// to see or modify the seasonal fruit that comes with the meal
// meal.seasonal_fruit = String::from("blueberries");
}
```
Listing 7-9: A struct with some public fields and some private fields
Listing 7-9: A struct with some public fields and some
private fields
Because the `toast` field in the `back_of_house::Breakfast` struct is public,
in `eat_at_restaurant` we can write and read to the `toast` field using dot
@ -705,7 +738,8 @@ pub fn eat_at_restaurant() {
}
```
Listing 7-10: Designating an enum as public makes all its variants public.
Listing 7-10: Designating an enum as public makes all its
variants public
Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
variants in `eat_at_restaurant`.
@ -720,7 +754,7 @@ Theres one more situation involving `pub` that we havent covered, and that
our last module system feature: the `use` keyword. Well cover `use` by itself
first, and then well show how to combine `pub` and `use`.
## Bringing Paths into Scope with the use Keyword
## Bringing Paths into Scope with the `use` Keyword
Having to write out the paths to call functions can feel inconvenient and
repetitive. In Listing 7-7, whether we chose the absolute or relative path to
@ -750,7 +784,8 @@ pub fn eat_at_restaurant() {
}
```
Listing 7-11: Bringing a module into scope with `use`
Listing 7-11: Bringing a module into scope with
`use`
Adding `use` and a path in a scope is similar to creating a symbolic link in
the filesystem. By adding `use crate::front_of_house::hosting` in the crate
@ -781,17 +816,25 @@ mod customer {
}
```
Listing 7-12: A `use` statement only applies in the scope its in.
Listing 7-12: A `use` statement only applies in the scope
its in
The compiler error shows that the shortcut no longer applies within the
`customer` module:
```
$ cargo build
Compiling restaurant v0.1.0 (file:///projects/restaurant)
error[E0433]: failed to resolve: use of undeclared crate or module `hosting`
--> src/lib.rs:11:9
|
11 | hosting::add_to_waitlist();
| ^^^^^^^ use of undeclared crate or module `hosting`
|
help: consider importing this module through its public re-export
|
10 + use crate::hosting;
|
warning: unused import: `crate::front_of_house::hosting`
--> src/lib.rs:7:5
@ -800,6 +843,10 @@ warning: unused import: `crate::front_of_house::hosting`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
For more information about this error, try `rustc --explain E0433`.
warning: `restaurant` (lib) generated 1 warning
error: could not compile `restaurant` (lib) due to 1 previous error; 1 warning emitted
```
Notice theres also a warning that the `use` is no longer used in its scope! To
@ -807,7 +854,7 @@ fix this problem, move the `use` within the `customer` module too, or reference
the shortcut in the parent module with `super::hosting` within the child
`customer` module.
### Creating Idiomatic use Paths
### Creating Idiomatic `use` Paths
In Listing 7-11, you might have wondered why we specified `use
crate::front_of_house::hosting` and then called `hosting::add_to_waitlist` in
@ -830,8 +877,8 @@ pub fn eat_at_restaurant() {
}
```
Listing 7-13: Bringing the `add_to_waitlist` function into scope with `use`,
which is unidiomatic
Listing 7-13: Bringing the `add_to_waitlist` function
into scope with `use`, which is unidiomatic
Although both Listing 7-11 and Listing 7-13 accomplish the same task, Listing
7-11 is the idiomatic way to bring a function into scope with `use`. Bringing
@ -857,7 +904,8 @@ fn main() {
}
```
Listing 7-14: Bringing `HashMap` into scope in an idiomatic way
Listing 7-14: Bringing `HashMap` into scope in an
idiomatic way
Theres no strong reason behind this idiom: its just the convention that has
emerged, and folks have gotten used to reading and writing Rust code this way.
@ -874,23 +922,23 @@ use std::fmt;
use std::io;
fn function1() -> fmt::Result {
--snip--
// --snip--
}
fn function2() -> io::Result<()> {
--snip--
// --snip--
}
```
Listing 7-15: Bringing two types with the same name into the same scope
requires using their parent modules.
Listing 7-15: Bringing two types with the same name into
the same scope requires using their parent modules.
As you can see, using the parent modules distinguishes the two `Result` types.
If instead we specified `use std::fmt::Result` and `use std::io::Result`, wed
have two `Result` types in the same scope, and Rust wouldnt know which one we
meant when we used `Result`.
### Providing New Names with the as Keyword
### Providing New Names with the `as` Keyword
Theres another solution to the problem of bringing two types of the same name
into the same scope with `use`: after the path, we can specify `as` and a new
@ -904,22 +952,23 @@ use std::fmt::Result;
use std::io::Result as IoResult;
fn function1() -> Result {
--snip--
// --snip--
}
fn function2() -> IoResult<()> {
--snip--
// --snip--
}
```
Listing 7-16: Renaming a type when its brought into scope with the `as` keyword
Listing 7-16: Renaming a type when its brought into
scope with the `as` keyword
In the second `use` statement, we chose the new name `IoResult` for the
`std::io::Result` type, which wont conflict with the `Result` from `std::fmt`
that weve also brought into scope. Listing 7-15 and Listing 7-16 are
considered idiomatic, so the choice is up to you!
### Re-exporting Names with pub use
### Re-exporting Names with `pub use`
When we bring a name into scope with the `use` keyword, the name available in
the new scope is private. To enable the code that calls our code to refer to
@ -947,12 +996,13 @@ pub fn eat_at_restaurant() {
}
```
Listing 7-17: Making a name available for any code to use from a new scope with
`pub use`
Listing 7-17: Making a name available for any code to use
from a new scope with `pub use`
Before this change, external code would have to call the `add_to_waitlist`
function by using the path
`restaurant::front_of_house::hosting::add_to_waitlist()`. Now that this `pub
`restaurant::front_of_house::hosting::add_to_waitlist()`, which also would have
required the `front_of_house` module to be marked as `pub`. Now that this `pub
use` has re-exported the `hosting` module from the root module, external code
can use the path `restaurant::hosting::add_to_waitlist()` instead.
@ -964,8 +1014,9 @@ probably wont think about the parts of the restaurant in those terms. With
`pub use`, we can write our code with one structure but expose a different
structure. Doing so makes our library well organized for programmers working on
the library and programmers calling the library. Well look at another example
of `pub use` and how it affects your crates documentation in “Exporting a
Convenient Public API with pub use” on page XX.
of `pub use` and how it affects your crates documentation in the “Exporting a
Convenient Public API with `pub use`” section of
Chapter 14.
### Using External Packages
@ -973,6 +1024,12 @@ In Chapter 2, we programmed a guessing game project that used an external
package called `rand` to get random numbers. To use `rand` in our project, we
added this line to *Cargo.toml*:
<!-- When updating the version of `rand` used, also update the version of
`rand` used in these files so they all match:
* ch02-00-guessing-game-tutorial.md
* ch14-03-cargo-workspaces.md
-->
Filename: Cargo.toml
```
@ -980,14 +1037,14 @@ rand = "0.8.5"
```
Adding `rand` as a dependency in *Cargo.toml* tells Cargo to download the
`rand` package and any dependencies from *https://crates.io*, and make `rand`
available to our project.
`rand` package and any dependencies from crates.io at *https://crates.io/* and
make `rand` available to our project.
Then, to bring `rand` definitions into the scope of our package, we added a
`use` line starting with the name of the crate, `rand`, and listed the items we
wanted to bring into scope. Recall that in “Generating a Random Number” on page
XX, we brought the `Rng` trait into scope and called the `rand::thread_rng`
function:
`use` line starting with the name of the crate, `rand`, and listed the items
we wanted to bring into scope. Recall that in the “Generating a Random
Number” section in Chapter 2, we brought the `Rng` trait
into scope and called the `rand::thread_rng` function:
```
use rand::Rng;
@ -998,9 +1055,9 @@ fn main() {
```
Members of the Rust community have made many packages available at
*https://crates.io*, and pulling any of them into your package involves these
same steps: listing them in your packages *Cargo.toml* file and using `use` to
bring items from their crates into scope.
crates.io at *https://crates.io/*, and pulling any of them into your package
involves these same steps: listing them in your packages *Cargo.toml* file and
using `use` to bring items from their crates into scope.
Note that the standard `std` library is also a crate thats external to our
package. Because the standard library is shipped with the Rust language, we
@ -1015,7 +1072,7 @@ use std::collections::HashMap;
This is an absolute path starting with `std`, the name of the standard library
crate.
### Using Nested Paths to Clean Up Large use Lists
### Using Nested Paths to Clean Up Large `use` Lists
If were using multiple items defined in the same crate or same module, listing
each item on its own line can take up a lot of vertical space in our files. For
@ -1025,10 +1082,10 @@ bring items from `std` into scope:
Filename: src/main.rs
```
--snip--
// --snip--
use std::cmp::Ordering;
use std::io;
--snip--
// --snip--
```
Instead, we can use nested paths to bring the same items into scope in one
@ -1039,13 +1096,13 @@ differ, as shown in Listing 7-18.
Filename: src/main.rs
```
--snip--
// --snip--
use std::{cmp::Ordering, io};
--snip--
// --snip--
```
Listing 7-18: Specifying a nested path to bring multiple items with the same
prefix into scope
Listing 7-18: Specifying a nested path to bring multiple
items with the same prefix into scope
In bigger programs, bringing many items into scope from the same crate or
module using nested paths can reduce the number of separate `use` statements
@ -1063,7 +1120,8 @@ use std::io;
use std::io::Write;
```
Listing 7-19: Two `use` statements where one is a subpath of the other
Listing 7-19: Two `use` statements where one is a subpath
of the other
The common part of these two paths is `std::io`, and thats the complete first
path. To merge these two paths into one `use` statement, we can use `self` in
@ -1075,7 +1133,8 @@ Filename: src/lib.rs
use std::io::{self, Write};
```
Listing 7-20: Combining the paths in Listing 7-19 into one `use` statement
Listing 7-20: Combining the paths in Listing 7-19 into
one `use` statement
This line brings `std::io` and `std::io::Write` into scope.
@ -1094,9 +1153,11 @@ harder to tell what names are in scope and where a name used in your program
was defined.
The glob operator is often used when testing to bring everything under test
into the `tests` module; well talk about that in “How to Write Tests” on page
XX. The glob operator is also sometimes used as part of the prelude pattern:
see the standard library documentation for more information on that pattern.
into the `tests` module; well talk about that in the “How to Write
Tests” section in Chapter 11. The glob operator
is also sometimes used as part of the prelude pattern: see the standard
library documentation
for more information on that pattern.
## Separating Modules into Different Files
@ -1128,8 +1189,8 @@ pub fn eat_at_restaurant() {
}
```
Listing 7-21: Declaring the `front_of_house` module whose body will be in
*src/front_of_house.rs*
Listing 7-21: Declaring the `front_of_house` module whose
body will be in *src/front_of_house.rs*
Next, place the code that was in the curly brackets into a new file named
*src/front_of_house.rs*, as shown in Listing 7-22. The compiler knows to look
@ -1144,16 +1205,17 @@ pub mod hosting {
}
```
Listing 7-22: Definitions inside the `front_of_house` module in
*src/front_of_house.rs*
Listing 7-22: Definitions inside the `front_of_house`
module in *src/front_of_house.rs*
Note that you only need to load a file using a `mod` declaration *once* in your
module tree. Once the compiler knows the file is part of the project (and knows
where in the module tree the code resides because of where youve put the `mod`
statement), other files in your project should refer to the loaded files code
using a path to where it was declared, as covered in “Paths for Referring to an
Item in the Module Tree” on page XX. In other words, `mod` is *not* an
“include” operation that you may have seen in other programming languages.
using a path to where it was declared, as covered in the “Paths for Referring
to an Item in the Module Tree” section. In other words,
`mod` is *not* an “include” operation that you may have seen in other
programming languages.
Next, well extract the `hosting` module to its own file. The process is a bit
different because `hosting` is a child module of `front_of_house`, not of the
@ -1187,26 +1249,26 @@ directories and files more closely match the module tree.
> ### Alternate File Paths
>
> So far weve covered the most idiomatic file paths the Rust compiler uses,
but Rust also supports an older style of file path. For a module named
`front_of_house` declared in the crate root, the compiler will look for the
modules code in:
> but Rust also supports an older style of file path. For a module named
> `front_of_house` declared in the crate root, the compiler will look for the
> modules code in:
>
> * *src/front_of_house.rs* (what we covered)
> * *src/front_of_house/mod.rs* (older style, still supported path)
>
> For a module named `hosting` that is a submodule of `front_of_house`, the
compiler will look for the modules code in:
> compiler will look for the modules code in:
>
> * *src/front_of_house/hosting.rs* (what we covered)
> * *src/front_of_house/hosting/mod.rs* (older style, still supported path)
>
> If you use both styles for the same module, youll get a compiler error.
Using a mix of both styles for different modules in the same project is
allowed, but might be confusing for people navigating your project.
> Using a mix of both styles for different modules in the same project is
> allowed, but might be confusing for people navigating your project.
>
> The main downside to the style that uses files named *mod.rs* is that your
project can end up with many files named *mod.rs*, which can get confusing when
you have them open in your editor at the same time.
> project can end up with many files named *mod.rs*, which can get confusing
> when you have them open in your editor at the same time.
Weve moved each modules code to a separate file, and the module tree remains
the same. The function calls in `eat_at_restaurant` will work without any
@ -1230,4 +1292,3 @@ definitions public by adding the `pub` keyword.
In the next chapter, well look at some collection data structures in the
standard library that you can use in your neatly organized code.

Some files were not shown because too many files have changed in this diff Show More