diff --git a/listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs index 9f38aa25c..453ce8506 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs @@ -25,7 +25,7 @@ fn main() { // ANCHOR_END: expect // ANCHOR: print_guess - println!("You guessed: {}", guess); // 次のように予想しました: {} + println!("You guessed: {guess}"); // 次のように予想しました: {guess} // ANCHOR_END: print_guess } // ANCHOR: all diff --git a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock index 0a2f222c2..0fb52b33c 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -8,9 +10,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "getrandom" -version = "0.2.2" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -26,33 +28,32 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -60,24 +61,15 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-02/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-02/src/main.rs index 60fb2a8e5..b35ed0f2f 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-02/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-02/src/main.rs @@ -11,5 +11,5 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); } diff --git a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs index 164bd46e8..bdacf04b5 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs @@ -8,10 +8,10 @@ fn main() { println!("Guess the number!"); // ANCHOR: ch07-04 - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); // ANCHOR_END: ch07-04 - println!("The secret number is: {}", secret_number); //秘密の数字は次の通り: {} + println!("The secret number is: {secret_number}"); //秘密の数字は次の通り: {secret_number} println!("Please input your guess."); @@ -21,7 +21,7 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); // ANCHOR: ch07-04 } // ANCHOR_END: ch07-04 diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt b/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt index 0c4b6f929..91598470c 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt @@ -5,42 +5,22 @@ $ cargo build Compiling ppv-lite86 v0.2.10 Compiling rand_core v0.6.2 Compiling rand_chacha v0.3.0 - Compiling rand v0.8.3 + Compiling rand v0.8.5 Compiling guessing_game v0.1.0 (file:///projects/guessing_game) error[E0308]: mismatched types (型が合いません) --> src/main.rs:22:21 | 22 | match guess.cmp(&secret_number) { - | ^^^^^^^^^^^^^^ expected struct `String`, found integer - | (構造体`std::string::String`を予期したけど、整数型変数が見つかりました) + | --- ^^^^^^^^^^^^^^ expected `&String`, found `&{integer}` + | | (`&String`を予期したけど、`&{integer}`が見つかりました) + | | + | arguments to this method are incorrect + | (このメソッドへの引数が正しくありません) | = note: expected reference `&String` found reference `&{integer}` +note: method defined here + --> /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/cmp.rs:814:8 -error[E0283]: type annotations needed for `{integer}` - --> src/main.rs:8:44 - | -8 | let secret_number = rand::thread_rng().gen_range(1..101); - | ------------- ^^^^^^^^^ cannot infer type for type `{integer}` - | | - | consider giving `secret_number` a type - | - = note: multiple `impl`s satisfying `{integer}: SampleUniform` found in the `rand` crate: - - impl SampleUniform for i128; - - impl SampleUniform for i16; - - impl SampleUniform for i32; - - impl SampleUniform for i64; - and 8 more -note: required by a bound in `gen_range` - --> /Users/carolnichols/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.3/src/rng.rs:129:12 - | -129 | T: SampleUniform, - | ^^^^^^^^^^^^^ required by this bound in `gen_range` -help: consider specifying the type arguments in the function call - | -8 | let secret_number = rand::thread_rng().gen_range::(1..101); - | ++++++++ - -Some errors have detailed explanations: E0283, E0308. -For more information about an error, try `rustc --explain E0283`. -error: could not compile `guessing_game` due to 2 previous errors (先の2つのエラーのため、`guessing_game`をコンパイルできませんでした) +For more information about this error, try `rustc --explain E0308`. +error: could not compile `guessing_game` (bin "guessing_game") due to 1 previous error (先の1つのエラーのため、`guessing_game` (bin "guessing_game") をコンパイルできませんでした) diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs index d22864972..eadbaf9f2 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs @@ -8,9 +8,9 @@ fn main() { // ANCHOR_END: here println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -21,7 +21,7 @@ fn main() { .expect("Failed to read line"); // ANCHOR: here - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), //小さすぎ! diff --git a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs index 41a4cdd14..12f497e18 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs @@ -5,9 +5,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); loop { println!("Please input your guess."); @@ -28,7 +28,7 @@ fn main() { }; // ANCHOR_END: ch19 - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); // --snip-- // ANCHOR_END: here diff --git a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs index 30859c70e..7fcbb99fb 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs @@ -5,7 +5,7 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); loop { println!("Please input your guess."); @@ -21,7 +21,7 @@ fn main() { Err(_) => continue, }; - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.lock index 5802b7dc9..ee5d79095 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "guessing_game" version = "0.1.0" - diff --git a/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt b/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt index 0c102c8c7..0905fd9d1 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt +++ b/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt @@ -1,14 +1,19 @@ $ cargo build Compiling guessing_game v0.1.0 (file:///projects/guessing_game) warning: unused `Result` that must be used -(警告: 使用されなければならない`std::result::Result`が使用されていません) +(警告: 使用されなければならない`Result`が使用されていません) --> src/main.rs:10:5 | 10 | io::stdin().read_line(&mut guess); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_must_use)]` on by default = note: this `Result` may be an `Err` variant, which should be handled + = note: `#[warn(unused_must_use)]` on by default +help: use `let _ = ...` to ignore the resulting value +(ヘルプ: 結果の値を無視するには `let _ = ...` を使用してください) + | +10 | let _ = io::stdin().read_line(&mut guess); + | +++++++ warning: `guessing_game` (bin "guessing_game") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.59s diff --git a/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/src/main.rs b/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/src/main.rs index aaf90bd65..51046016f 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/src/main.rs @@ -9,5 +9,5 @@ fn main() { io::stdin().read_line(&mut guess); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); } diff --git a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs index cd0962ce9..a4af2240f 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs @@ -5,9 +5,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -20,10 +20,9 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - let guess: u32 = guess.trim().parse() - .expect("Please type a number!"); //数値を入力してください! + let guess: u32 = guess.trim().parse().expect("Please type a number!"); //数値を入力してください! - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs index 61a5dc018..f97d1c58c 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs @@ -5,12 +5,12 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); // ANCHOR: here // --snip-- - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); loop { println!("Please input your guess."); @@ -27,7 +27,7 @@ fn main() { let guess: u32 = guess.trim().parse().expect("Please type a number!"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); // ANCHOR: here match guess.cmp(&secret_number) { diff --git a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs index 3f8e8b771..def0a0e7e 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs @@ -5,9 +5,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); loop { println!("Please input your guess."); @@ -20,7 +20,7 @@ fn main() { let guess: u32 = guess.trim().parse().expect("Please type a number!"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); // ANCHOR: here // --snip-- diff --git a/listings/ch03-common-programming-concepts/listing-03-02/src/main.rs b/listings/ch03-common-programming-concepts/listing-03-02/src/main.rs index bd5b900c4..9386ad697 100644 --- a/listings/ch03-common-programming-concepts/listing-03-02/src/main.rs +++ b/listings/ch03-common-programming-concepts/listing-03-02/src/main.rs @@ -2,6 +2,6 @@ fn main() { let condition = true; let number = if condition { 5 } else { 6 }; - // numberの値は、{}です - println!("The value of number is: {}", number); + // numberの値は、{number}です + println!("The value of number is: {number}"); } diff --git a/listings/ch03-common-programming-concepts/listing-03-03/src/main.rs b/listings/ch03-common-programming-concepts/listing-03-03/src/main.rs index 568f2bc8e..64720815c 100644 --- a/listings/ch03-common-programming-concepts/listing-03-03/src/main.rs +++ b/listings/ch03-common-programming-concepts/listing-03-03/src/main.rs @@ -2,7 +2,7 @@ fn main() { let mut number = 3; while number != 0 { - println!("{}!", number); + println!("{number}!"); number -= 1; } diff --git a/listings/ch03-common-programming-concepts/listing-03-05/src/main.rs b/listings/ch03-common-programming-concepts/listing-03-05/src/main.rs index 5eaa7a09e..b44e6b7aa 100644 --- a/listings/ch03-common-programming-concepts/listing-03-05/src/main.rs +++ b/listings/ch03-common-programming-concepts/listing-03-05/src/main.rs @@ -2,6 +2,6 @@ fn main() { let a = [10, 20, 30, 40, 50]; for element in a { - println!("the value is: {}", element); + println!("the value is: {element}"); } } diff --git a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt index 127a0b902..4e76fa360 100644 --- a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt @@ -10,9 +10,9 @@ error[E0384]: cannot assign twice to immutable variable `x` | first assignment to `x` | (`x`への最初の代入) | help: consider making this binding mutable: `mut x` -3 | println!("The value of x is: {}", x); +3 | println!("The value of x is: {x}"); 4 | x = 6; | ^^^^^ cannot assign twice to immutable variable For more information about this error, try `rustc --explain E0384`. -error: could not compile `variables` due to previous error +error: could not compile `variables` (bin "variables") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs index 84d0ad8d9..046fbb406 100644 --- a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs @@ -1,6 +1,6 @@ fn main() { let x = 5; - println!("The value of x is: {}", x); // xの値は{}です + println!("The value of x is: {x}"); // xの値は{x}です x = 6; - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs index c4e4a1953..a57709ccf 100644 --- a/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs @@ -1,6 +1,6 @@ fn main() { let mut x = 5; - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); x = 6; - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs index 606ee68a0..03924fe1c 100644 --- a/listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs @@ -5,8 +5,8 @@ fn main() { { let x = x * 2; - println!("The value of x in the inner scope is: {}", x); + println!("The value of x in the inner scope is: {x}"); } - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt b/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt index 0bf395c6e..271ed387c 100644 --- a/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt @@ -8,6 +8,12 @@ error[E0308]: mismatched types (型が合いません) 3 | spaces = spaces.len(); | ^^^^^^^^^^^^ expected `&str`, found `usize` | (&str型を予期しましたが、usizeが見つかりました) + | +help: try removing the method call + | +3 - spaces = spaces.len(); +3 + spaces = spaces; + | For more information about this error, try `rustc --explain E0308`. -error: could not compile `variables` due to previous error +error: could not compile `variables` (bin "variables") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs index 2bd8f9204..df79eb4f1 100644 --- a/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs @@ -14,8 +14,8 @@ fn main() { // division // 割り算 let quotient = 56.7 / 32.2; - let floored = 2 / 3; // Results in 0 - // 結果は0 + let truncated = -5 / 3; // Results in -1 + // 結果は-1 // remainder // 余り diff --git a/listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs index b52bd7f5c..1043f3990 100644 --- a/listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs @@ -1,5 +1,6 @@ fn main() { let c = 'z'; - let z = 'ℤ'; + let z: char = 'ℤ'; // with explicit type annotation + // 明示的型注釈付きで let heart_eyed_cat = '😻'; //ハート目の猫 } diff --git a/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs index 35dcb442e..3002bdde4 100644 --- a/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs @@ -3,5 +3,5 @@ fn main() { let (x, y, z) = tup; - println!("The value of y is: {}", y); + println!("The value of y is: {y}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs index a7b70697b..9d1cfcd55 100644 --- a/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs @@ -21,9 +21,6 @@ fn main() { let element = a[index]; - println!( - "The value of the element at index {} is: {}", - // {}番目の要素の値は{}です - index, element - ); + println!("The value of the element at index {index} is: {element}"); + // {index}番目の要素の値は{element}です } diff --git a/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs index 47655ec8b..e13d54d2e 100644 --- a/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs @@ -3,5 +3,5 @@ fn main() { } fn another_function(x: i32) { - println!("The value of x is: {}", x); // xの値は{}です + println!("The value of x is: {x}"); // xの値は{x}です } diff --git a/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs index 543c2ea45..b070ccb23 100644 --- a/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs @@ -3,5 +3,5 @@ fn main() { } fn print_labeled_measurement(value: i32, unit_label: char) { - println!("The measurement is: {}{}", value, unit_label); + println!("The measurement is: {value}{unit_label}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt b/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt index 4cf947530..2f99beed6 100644 --- a/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt @@ -1,23 +1,14 @@ $ cargo run Compiling functions v0.1.0 (file:///projects/functions) -error: expected expression, found statement (`let`) -(エラー: 式を予期しましたが、文が見つかりました (`let`)) +error: expected expression, found `let` statement +(エラー: 式を予期しましたが、`let`文が見つかりました) --> src/main.rs:2:14 | 2 | let x = (let y = 6); - | ^^^^^^^^^ + | ^^^ | - = note: variable declaration using `let` is a statement - (注釈: `let`を使う変数宣言は、文です) - -error[E0658]: `let` expressions in this position are experimental - --> src/main.rs:2:14 - | -2 | let x = (let y = 6); - | ^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: you can write `matches!(, )` instead of `let = ` + = note: only supported directly in conditions of `if` and `while` expressions + (注釈: `if` および `while` 式の条件部直下でのみ対応しています warning: unnecessary parentheses around assigned value --> src/main.rs:2:13 @@ -30,8 +21,7 @@ help: remove these parentheses | 2 - let x = (let y = 6); 2 + let x = let y = 6; - | + | -For more information about this error, try `rustc --explain E0658`. warning: `functions` (bin "functions") generated 1 warning -error: could not compile `functions` due to 2 previous errors; 1 warning emitted +error: could not compile `functions` (bin "functions") due to 1 previous error; 1 warning emitted diff --git a/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs index 0be7fcbf3..64b873297 100644 --- a/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs @@ -4,5 +4,5 @@ fn main() { x + 1 }; - println!("The value of y is: {}", y); + println!("The value of y is: {y}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs index 5303b1082..a11af7ec7 100644 --- a/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs @@ -5,5 +5,5 @@ fn five() -> i32 { fn main() { let x = five(); - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs index b4c84437a..da9d0ddb3 100644 --- a/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs @@ -1,7 +1,7 @@ fn main() { let x = plus_one(5); - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } fn plus_one(x: i32) -> i32 { diff --git a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt index 7a684650a..d13b1c891 100644 --- a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt @@ -9,7 +9,7 @@ error[E0308]: mismatched types | | | implicitly returns `()` as its body has no tail or `return` expression 8 | x + 1; - | - help: consider removing this semicolon + | - help: remove this semicolon to return this value For more information about this error, try `rustc --explain E0308`. -error: could not compile `functions` due to previous error +error: could not compile `functions` (bin "functions") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs index c9c4edc19..1cec800b6 100644 --- a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs @@ -1,7 +1,7 @@ fn main() { let x = plus_one(5); - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } fn plus_one(x: i32) -> i32 { diff --git a/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt b/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt index 3a43db713..e8f033d36 100644 --- a/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt @@ -9,4 +9,4 @@ error[E0308]: mismatched types | (bool型を予期したのに、整数変数が見つかりました) For more information about this error, try `rustc --explain E0308`. -error: could not compile `branches` due to previous error +error: could not compile `branches` (bin "branches") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt b/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt index a236054af..7e11035d3 100644 --- a/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt @@ -11,4 +11,4 @@ error[E0308]: `if` and `else` have incompatible types | expected because of this For more information about this error, try `rustc --explain E0308`. -error: could not compile `branches` due to previous error +error: could not compile `branches` (bin "branches") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs index 440b286f5..df7068bcf 100644 --- a/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs @@ -3,5 +3,5 @@ fn main() { let number = if condition { 5 } else { "six" }; - println!("The value of number is: {}", number); + println!("The value of number is: {number}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs index b855d7576..dd8856403 100644 --- a/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs @@ -1,11 +1,11 @@ fn main() { let mut count = 0; 'counting_up: loop { - println!("count = {}", count); + println!("count = {count}"); let mut remaining = 10; loop { - println!("remaining = {}", remaining); + println!("remaining = {remaining}"); if remaining == 9 { break; } @@ -17,5 +17,5 @@ fn main() { count += 1; } - println!("End count = {}", count); + println!("End count = {count}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs index 6ffdab5a4..683d18bc1 100644 --- a/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs @@ -9,5 +9,5 @@ fn main() { } }; - println!("The result is {}", result); + println!("The result is {result}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs index e7286a84e..df5b305bc 100644 --- a/listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs @@ -1,6 +1,6 @@ fn main() { for number in (1..4).rev() { - println!("{}!", number); + println!("{number}!"); } println!("LIFTOFF!!!"); } diff --git a/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt b/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt index 8072cd10f..ded0312d5 100644 --- a/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt +++ b/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt @@ -1,12 +1,20 @@ $ cargo build Compiling no_type_annotations v0.1.0 (file:///projects/no_type_annotations) -error[E0282]: type annotations needed +error[E0284]: type annotations needed (型注釈が必要です) --> src/main.rs:2:9 | 2 | let guess = "42".parse().expect("Not a number!"); - | ^^^^^ consider giving `guess` a type - | (`guess`に型を与えることを検討してください) + | ^^^^^ ----- type must be known at this point + | (型はこの時点で既知でなくてはなりません) + | + = note: cannot satisfy `<_ as FromStr>::Err == _` + (`<_ as FromStr>::Err == _`を満たすことができません) +help: consider giving `guess` an explicit type + | (`guess`に型を与えることを検討してください) + | +2 | let guess: /* Type */ = "42".parse().expect("Not a number!"); + | ++++++++++++ -For more information about this error, try `rustc --explain E0282`. -error: could not compile `no_type_annotations` due to previous error +For more information about this error, try `rustc --explain E0284`. +error: could not compile `no_type_annotations` (bin "no_type_annotations") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-01/src/main.rs b/listings/ch04-understanding-ownership/listing-04-01/src/main.rs index 148ad84c9..baee5d9ab 100644 --- a/listings/ch04-understanding-ownership/listing-04-01/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-01/src/main.rs @@ -1,9 +1,9 @@ fn main() { // ANCHOR: here - { // s is not valid here, it’s not yet declared - let s = "hello"; // s is valid from this point forward + { // sは、ここでは有効ではない。まだ宣言されていない + let s = "hello"; // sは、ここから有効になる - // do stuff with s - } // this scope is now over, and s is no longer valid + // sで作業をする + } // このスコープは終わり。もうsは有効ではない // ANCHOR_END: here } \ No newline at end of file diff --git a/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-03/src/main.rs b/listings/ch04-understanding-ownership/listing-04-03/src/main.rs index 23906b430..221679d95 100644 --- a/listings/ch04-understanding-ownership/listing-04-03/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-03/src/main.rs @@ -1,23 +1,23 @@ fn main() { - let s = String::from("hello"); // s comes into scope + let s = String::from("hello"); // sがスコープに入る - takes_ownership(s); // s's value moves into the function... - // ... and so is no longer valid here + takes_ownership(s); // sの値が関数にムーブされ... + // ... ここではもう有効ではない - let x = 5; // x comes into scope + let x = 5; // xがスコープに入る - makes_copy(x); // x would move into the function, - // but i32 is Copy, so it’s okay to still - // use x afterward + makes_copy(x); // xも関数にムーブされるが、 + // i32はCopyなので、この後にxを使っても + // 大丈夫 -} // Here, x goes out of scope, then s. But because s's value was moved, nothing - // special happens. +} // ここでxがスコープを抜け、sもスコープを抜ける。ただし、sの値はムーブされているので、 + // 何も特別なことは起こらない。 -fn takes_ownership(some_string: String) { // some_string comes into scope +fn takes_ownership(some_string: String) { // some_stringがスコープに入る。 println!("{}", some_string); -} // Here, some_string goes out of scope and `drop` is called. The backing - // memory is freed. +} // ここでsome_stringがスコープを抜け、`drop`が呼ばれる。後ろ盾してたメモリが解放される。 + // 後ろ盾してたメモリが解放される。 -fn makes_copy(some_integer: i32) { // some_integer comes into scope +fn makes_copy(some_integer: i32) { // some_integerがスコープに入る println!("{}", some_integer); -} // Here, some_integer goes out of scope. Nothing special happens. +} // ここでsome_integerがスコープを抜ける。何も特別なことはない。 diff --git a/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-04/src/main.rs b/listings/ch04-understanding-ownership/listing-04-04/src/main.rs index e3e54a818..bb3aa1842 100644 --- a/listings/ch04-understanding-ownership/listing-04-04/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-04/src/main.rs @@ -1,29 +1,25 @@ fn main() { - let s1 = gives_ownership(); // gives_ownership moves its return - // value into s1 + let s1 = gives_ownership(); // gives_ownershipは、戻り値をs1に + // ムーブする - let s2 = String::from("hello"); // s2 comes into scope + let s2 = String::from("hello"); // s2がスコープに入る - let s3 = takes_and_gives_back(s2); // s2 is moved into - // takes_and_gives_back, which also - // moves its return value into s3 -} // Here, s3 goes out of scope and is dropped. s2 goes out of scope but was - // moved, so nothing happens. s1 goes out of scope and is dropped. + let s3 = takes_and_gives_back(s2); // s2はtakes_and_gives_backにムーブされ + // 戻り値もs3にムーブされる +} // ここで、s3はスコープを抜け、ドロップされる。s2もスコープを抜けるが、ムーブされているので、 + // 何も起きない。s1もスコープを抜け、ドロップされる。 -fn gives_ownership() -> String { // gives_ownership will move its - // return value into the function - // that calls it +fn gives_ownership() -> String { // gives_ownershipは、戻り値を + // 呼び出した関数にムーブする - let some_string = String::from("hello"); // some_string comes into scope + let some_string = String::from("hello"); // some_stringがスコープに入る - some_string // some_string is returned and - // moves out to the calling - // function + some_string // some_stringが返され、呼び出し元関数に + // ムーブされる } -// takes_and_gives_back will take a String and return one -fn takes_and_gives_back(a_string: String) -> String { // a_string comes into - // scope +// takes_and_gives_backは、Stringを一つ受け取り、返す。 +fn takes_and_gives_back(a_string: String) -> String { // a_stringがスコープに入る。 - a_string // a_string is returned and moves out to the calling function + a_string // a_stringが返され、呼び出し元関数にムーブされる } diff --git a/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-05/src/main.rs b/listings/ch04-understanding-ownership/listing-04-05/src/main.rs index 22aee1419..1f0faaa93 100644 --- a/listings/ch04-understanding-ownership/listing-04-05/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-05/src/main.rs @@ -3,11 +3,12 @@ fn main() { let (s2, len) = calculate_length(s1); + //'{}'の長さは、{}です println!("The length of '{}' is {}.", s2, len); } fn calculate_length(s: String) -> (String, usize) { - let length = s.len(); // len() returns the length of a String + let length = s.len(); // len()メソッドは、Stringの長さを返します (s, length) } diff --git a/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-06/output.txt b/listings/ch04-understanding-ownership/listing-04-06/output.txt index 98f438f61..019356390 100644 --- a/listings/ch04-understanding-ownership/listing-04-06/output.txt +++ b/listings/ch04-understanding-ownership/listing-04-06/output.txt @@ -1,16 +1,18 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference + (`*some_string`は`&`参照の背後にあるため、それを可変として借用することはできません) --> src/main.rs:8:5 | -7 | fn change(some_string: &String) { - | ------- help: consider changing this to be a mutable reference: `&mut std::string::String` 8 | some_string.push_str(", world"); | ^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable - -error: aborting due to previous error + | (`some_string`は`&`参照なので、それが指すデータを可変として借用することはできません) + | +help: consider changing this to be a mutable reference + (これを可変参照に変更することを検討してください) + | +7 | fn change(some_string: &mut String) { + | +++ For more information about this error, try `rustc --explain E0596`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml index dddcb5a14..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Carol (Nichols || Goulding) "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-09/src/main.rs b/listings/ch04-understanding-ownership/listing-04-09/src/main.rs index b3447e826..fb632583d 100644 --- a/listings/ch04-understanding-ownership/listing-04-09/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-09/src/main.rs @@ -16,14 +16,21 @@ fn first_word(s: &str) -> &str { fn main() { let my_string = String::from("hello world"); - // first_word works on slices of `String`s - // first_wordは`String`のスライスに対して機能する + // `first_word` works on slices of `String`s, whether partial or whole + // `first_word`は`String`の全体または部分へのスライスに対して機能する + let word = first_word(&my_string[0..6]); let word = first_word(&my_string[..]); + // `first_word` also works on references to `String`s, which are equivalent + // to whole slices of `String`s + // `first_word`は`String`の参照に対しても機能する。この場合は + // `String`全体へのスライスと同等。 + let word = first_word(&my_string); let my_string_literal = "hello world"; - // first_word works on slices of string literals - // first_wordは文字列リテラルのスライスに対して機能する + // `first_word` works on slices of string literals, whether partial or whole + // `first_word`は文字列リテラルの全体または部分へのスライスに対して機能する + let word = first_word(&my_string_literal[0..6]); let word = first_word(&my_string_literal[..]); // Because string literals *are* string slices already, diff --git a/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs b/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs index b68f0f1e7..e9782f2d6 100644 --- a/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs @@ -2,8 +2,8 @@ fn main() { // ANCHOR: here let mut s = String::from("hello"); - s.push_str(", world!"); // push_str() appends a literal to a String + s.push_str(", world!"); // push_str()関数は、リテラルをStringに付け加える - println!("{}", s); // This will print `hello, world!` + println!("{}", s); // これは`hello, world!`と出力する // ANCHOR_END: here } diff --git a/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs b/listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs index 7e6d46f83..db803b700 100644 --- a/listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs @@ -1,10 +1,10 @@ fn main() { // ANCHOR: here - { - let s = String::from("hello"); // s is valid from this point forward + { + let s = String::from("hello"); // sはここから有効になる - // do stuff with s - } // this scope is now over, and s is no - // longer valid + // sで作業をする + } // このスコープはここでおしまい。sは + // もう有効ではない // ANCHOR_END: here } diff --git a/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt index 910332ac1..793b6a6e9 100644 --- a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt @@ -1,19 +1,25 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0382]: borrow of moved value: `s1` + (ムーブされた値の借用: `s1`) --> src/main.rs:5:28 | 2 | let s1 = String::from("hello"); - | -- move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait + | -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait + | (`s1`は`String`型を持ち、これは`Copy`トレイトを実装していないので、ムーブが発生します) 3 | let s2 = s1; | -- value moved here -4 | + | (ここで値がムーブされました) +4 | 5 | println!("{}, world!", s1); | ^^ value borrowed here after move - -error: aborting due to previous error + | (ムーブ後にここで借用されています) + | + = 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 + | +3 | let s2 = s1.clone(); + | ++++++++ For more information about this error, try `rustc --explain E0382`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs b/listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs index fd32a5fc9..34ca14ed5 100644 --- a/listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs @@ -6,6 +6,7 @@ fn main() { let len = calculate_length(&s1); // ANCHOR_END: here + // '{}'の長さは、{}です println!("The length of '{}' is {}.", s1, len); } diff --git a/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs b/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs index 6e40b8c30..73704d016 100644 --- a/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs @@ -7,8 +7,8 @@ fn main() { } // ANCHOR: here -fn calculate_length(s: &String) -> usize { // s is a reference to a String +fn calculate_length(s: &String) -> usize { // sはStringへの参照 s.len() -} // Here, s goes out of scope. But because it does not have ownership of what - // it refers to, nothing happens. +} // ここで、sはスコープ外になる。けど、参照しているものの所有権を持っているわけではないので + // 何も起こらない // ANCHOR_END: here diff --git a/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt index cb69a714b..ae47fb288 100644 --- a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt @@ -1,19 +1,19 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0499]: cannot borrow `s` as mutable more than once at a time + (一度に`s`を可変として2回以上借用することはできません) --> src/main.rs:5:14 | 4 | let r1 = &mut s; | ------ first mutable borrow occurs here + | (最初の可変借用はここで発生しています) 5 | let r2 = &mut s; | ^^^^^^ second mutable borrow occurs here -6 | + | (2つ目の可変借用はここで発生しています) +6 | 7 | println!("{}, {}", r1, r2); | -- first borrow later used here - -error: aborting due to previous error + | (最初の参照はここで後で使用されています) For more information about this error, try `rustc --explain E0499`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs b/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs index 4b1a5a383..f8b382574 100644 --- a/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs @@ -4,7 +4,7 @@ fn main() { { let r1 = &mut s; - } // r1 goes out of scope here, so we can make a new reference with no problems. + } // r1はここでスコープを抜けるので、問題なく新しい参照を作ることができる。 let r2 = &mut s; // ANCHOR_END: here diff --git a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt index cd4168f8c..af9520170 100644 --- a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt @@ -1,20 +1,20 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable + (`s`は不変で借用されているので、可変で借用できません) --> src/main.rs:6:14 | -4 | let r1 = &s; // no problem +4 | let r1 = &s; // 問題なし | -- immutable borrow occurs here -5 | let r2 = &s; // no problem -6 | let r3 = &mut s; // BIG PROBLEM + | (不変借用はここで発生しています) +5 | let r2 = &s; // 問題なし +6 | let r3 = &mut s; // 大問題! | ^^^^^^ mutable borrow occurs here -7 | + | (可変借用はここで発生しています) +7 | 8 | println!("{}, {}, and {}", r1, r2, r3); | -- immutable borrow later used here - -error: aborting due to previous error + | (不変借用はその後ここで使われています) For more information about this error, try `rustc --explain E0502`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs index 0da04c010..4d145502d 100644 --- a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs @@ -2,9 +2,9 @@ fn main() { // ANCHOR: here let mut s = String::from("hello"); - let r1 = &s; // no problem - let r2 = &s; // no problem - let r3 = &mut s; // BIG PROBLEM + let r1 = &s; // 問題なし + let r2 = &s; // 問題なし + let r3 = &mut s; // 大問題! println!("{}, {}, and {}", r1, r2, r3); // ANCHOR_END: here diff --git a/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs b/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs index 3b0a7da65..751a87472 100644 --- a/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs @@ -2,12 +2,12 @@ fn main() { // ANCHOR: here let mut s = String::from("hello"); - let r1 = &s; // no problem - let r2 = &s; // no problem + let r1 = &s; // 問題なし + let r2 = &s; // 問題なし println!("{} and {}", r1, r2); - // r1 and r2 are no longer used after this point + // r1とr2はもうこれ以降使用されません - let r3 = &mut s; // no problem + let r3 = &mut s; // 問題なし println!("{}", r3); // ANCHOR_END: here } diff --git a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt index 6381d2a30..c049f9e0e 100644 --- a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt @@ -1,16 +1,26 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0106]: missing lifetime specifier +(エラー: ライフタイム指定子がありません) --> src/main.rs:5:16 | 5 | fn dangle() -> &String { - | ^ help: consider giving it a 'static lifetime: `&'static` + | ^ expected named lifetime parameter + | (名前付きのライフタイムパラメータが期待されていました) | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - -error: aborting due to previous error + = (助言: この関数の戻り値型は、借用した値を含んでいますが、借用される値がどこにもありません) +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` +(助言: `'static`ライフタイムを使うことを検討してください、ただし`const`または`static`から借用した値を返すのでない限り、これはあまり使われません) + | +5 | fn dangle() -> &'static String { + | +++++++ +help: instead, you are more likely to want to return an owned value +(助言: または、所有権を持つ値を返す方がいいかもしれません) + | +5 - fn dangle() -> &String { +5 + fn dangle() -> String { + | For more information about this error, try `rustc --explain E0106`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs b/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs index 9fbb372a0..7cd451070 100644 --- a/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs @@ -3,11 +3,11 @@ fn main() { } // ANCHOR: here -fn dangle() -> &String { // dangle returns a reference to a String +fn dangle() -> &String { // dangleはStringへの参照を返す - let s = String::from("hello"); // s is a new String + let s = String::from("hello"); // sは新しいString - &s // we return a reference to the String, s -} // Here, s goes out of scope, and is dropped. Its memory goes away. - // Danger! + &s // String sへの参照を返す +} // ここで、sはスコープを抜け、ドロップされる。そのメモリは消される。 + // 危険だ // ANCHOR_END: here diff --git a/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt b/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt index a1d9caf11..26341bfc5 100644 --- a/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt @@ -7,18 +7,14 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta 16 | let word = first_word(&s); | -- immutable borrow occurs here | (不変借用はここで発生しています) -17 | +17 | 18 | s.clear(); // error! | ^^^^^^^^^ mutable borrow occurs here | (可変借用はここで発生しています) -19 | +19 | 20 | println!("the first word is: {}", word); | ---- immutable borrow later used here (不変借用はその後ここで使われています) -error: aborting due to previous error - For more information about this error, try `rustc --explain E0502`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs index a7cff6ec2..16dd15b29 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs @@ -1,9 +1,9 @@ // ANCHOR: here struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } // ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs index 390c8ff19..122d25164 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs @@ -1,17 +1,17 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } +// ANCHOR: here fn main() { - // ANCHOR: here let user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), active: true, + username: String::from("someusername123"), + email: String::from("someone@example.com"), sign_in_count: 1, }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs index c599c9d60..35eea8a9a 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs @@ -1,19 +1,19 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } +// ANCHOR: here fn main() { - // ANCHOR: here let mut user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), active: true, + username: String::from("someusername123"), + email: String::from("someone@example.com"), sign_in_count: 1, }; user1.email = String::from("anotheremail@example.com"); - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs index f934d4c00..8614561c1 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs @@ -1,16 +1,16 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } // ANCHOR: here fn build_user(email: String, username: String) -> User { User { - email: email, - username: username, active: true, + username: username, + email: email, sign_in_count: 1, } } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs index 1833aa8e4..c893c86a9 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs @@ -1,16 +1,16 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } // ANCHOR: here fn build_user(email: String, username: String) -> User { User { - email, - username, active: true, + username, + email, sign_in_count: 1, } } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs index 6c6d83d9b..15e7690e1 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs @@ -1,24 +1,28 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } +// ANCHOR: here fn main() { + // --snip-- + // ANCHOR_END: here + let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; - // ANCHOR: here + let user2 = User { - email: String::from("another@example.com"), - username: String::from("anotherusername567"), active: user1.active, + username: user1.username, + email: String::from("another@example.com"), sign_in_count: user1.sign_in_count, }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs index 17cef457b..008ad18f6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs @@ -1,23 +1,26 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } +// ANCHOR: here fn main() { + // --snip-- + // ANCHOR_END: here + let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; - // ANCHOR: here + let user2 = User { email: String::from("another@example.com"), - username: String::from("anotherusername567"), ..user1 }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt index 88e10d320..aaedb98a4 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt @@ -1,5 +1,6 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) + Compiling rectangles v0.1.0 (file:///projects/rectangles) Finished dev [unoptimized + debuginfo] target(s) in 0.42s - Running `target/debug/structs` + Running `target/debug/rectangles` The area of the rectangle is 1500 square pixels. +(長方形の面積は、1500平方ピクセルです) diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs index f324529fd..587e870bb 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs @@ -4,6 +4,7 @@ fn main() { let height1 = 50; println!( + // 長方形の面積は、{}平方ピクセルです "The area of the rectangle is {} square pixels.", area(width1, height1) ); diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt index 1e03d0625..d19319d00 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt @@ -1,6 +1,7 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) + Compiling rectangles v0.1.0 (file:///projects/rectangles) error[E0277]: `Rectangle` doesn't implement `std::fmt::Display` +(エラー: `Rectangle`は`std::fmt::Display`を実装していません) --> src/main.rs:12:29 | 12 | println!("rect1 is {}", rect1); @@ -8,11 +9,9 @@ error[E0277]: `Rectangle` doesn't implement `std::fmt::Display` | = help: the trait `std::fmt::Display` is not implemented for `Rectangle` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = note: required by `std::fmt::Display::fmt` - -error: aborting due to previous error + (ヘルプ: `std::fmt::Display`は`Rectangle`に対して実装されていません) + (注釈: フォーマット文字列では代わりに`{:?}`(またはpretty-printするためには{:#?})が使用できるかもしれません) + = 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) For more information about this error, try `rustc --explain E0277`. -error: could not compile `structs`. - -To learn more, run the command again with --verbose. +error: could not compile `rectangles` (bin "rectangles") due to 1 previous error diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs index 0ff8dcc8c..5e45f74e8 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs @@ -9,5 +9,6 @@ fn main() { height: 50, }; + // rect1は{}です println!("rect1 is {}", rect1); } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt index 3abfb4257..c37be6b5b 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt @@ -1,5 +1,5 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) + Compiling rectangles v0.1.0 (file:///projects/rectangles) Finished dev [unoptimized + debuginfo] target(s) in 0.48s - Running `target/debug/structs` + Running `target/debug/rectangles` rect1 is Rectangle { width: 30, height: 50 } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs index e4f45e868..a5c6cb1f9 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs @@ -17,6 +17,7 @@ fn main() { }; println!( + // 長方形の面積は{}平方ピクセルです。 "The area of the rectangle is {} square pixels.", rect1.area() ); diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs index 4c92c5d77..0d993162b 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs @@ -1,9 +1,7 @@ -fn main() { - // ANCHOR: here - struct Color(i32, i32, i32); - struct Point(i32, i32, i32); +struct Color(i32, i32, i32); +struct Point(i32, i32, i32); +fn main() { let black = Color(0, 0, 0); let origin = Point(0, 0, 0); - // ANCHOR_END: here } diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml index dec1c4bd5..d36dbc1d3 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt index 9a75534c3..5f9344c51 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt @@ -1,20 +1,31 @@ $ cargo run Compiling structs v0.1.0 (file:///projects/structs) error[E0106]: missing lifetime specifier - --> src/main.rs:2:15 + --> src/main.rs:3:15 + | +3 | username: &str, + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +1 ~ struct User<'a> { +2 | active: bool, +3 ~ username: &'a str, | -2 | username: &str, - | ^ expected lifetime parameter error[E0106]: missing lifetime specifier - --> src/main.rs:3:12 + --> src/main.rs:4:12 + | +4 | email: &str, + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +1 ~ struct User<'a> { +2 | active: bool, +3 | username: &str, +4 ~ email: &'a str, | -3 | email: &str, - | ^ expected lifetime parameter - -error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0106`. -error: could not compile `structs`. - -To learn more, run the command again with --verbose. +error: could not compile `structs` (bin "structs") due to 2 previous errors diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs index 3cf6ffa4f..96092d042 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs @@ -1,8 +1,8 @@ struct User { + active: bool, username: &str, email: &str, sign_in_count: u64, - active: bool, } fn main() { diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs index d5b1692a4..47fedc552 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs @@ -6,8 +6,8 @@ struct Rectangle { // ANCHOR: here impl Rectangle { - fn square(size: u32) -> Rectangle { - Rectangle { + fn square(size: u32) -> Self { + Self { width: size, height: size, } diff --git a/listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.lock similarity index 80% rename from listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.lock rename to listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.lock index 1fa96b797..fb30ed9c8 100644 --- a/listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "error-handling" +name = "structs" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml new file mode 100644 index 000000000..3232b6065 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "structs" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs new file mode 100644 index 000000000..d48c94e99 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs @@ -0,0 +1,5 @@ +struct AlwaysEqual; + +fn main() { + let subject = AlwaysEqual; +} diff --git a/listings/ch08-common-collections/listing-08-26/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.lock similarity index 84% rename from listings/ch08-common-collections/listing-08-26/Cargo.lock rename to listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.lock index d3daeff7d..4aabe7da6 100644 --- a/listings/ch08-common-collections/listing-08-26/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "collections" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml new file mode 100644 index 000000000..4a279a450 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rectangles" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt new file mode 100644 index 000000000..bfb88ebee --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt @@ -0,0 +1,9 @@ +$ cargo run + Compiling rectangles v0.1.0 (file:///projects/rectangles) + Finished dev [unoptimized + debuginfo] target(s) in 0.61s + Running `target/debug/rectangles` +[src/main.rs:10:16] 30 * scale = 60 +[src/main.rs:14:5] &rect1 = Rectangle { + width: 60, + height: 50, +} diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs new file mode 100644 index 000000000..dd0342959 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs @@ -0,0 +1,15 @@ +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +fn main() { + let scale = 2; + let rect1 = Rectangle { + width: dbg!(30 * scale), + height: 50, + }; + + dbg!(&rect1); +} diff --git a/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.lock similarity index 82% rename from listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.lock rename to listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.lock index 1fa96b797..4aabe7da6 100644 --- a/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "error-handling" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml new file mode 100644 index 000000000..4a279a450 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rectangles" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs new file mode 100644 index 000000000..f893f095c --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs @@ -0,0 +1,25 @@ +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +// ANCHOR: here +impl Rectangle { + fn width(&self) -> bool { + self.width > 0 + } +} + +fn main() { + let rect1 = Rectangle { + width: 30, + height: 50, + }; + + if rect1.width() { + // 長方形は非ゼロの幅を持っています; それは{}です + println!("The rectangle has a nonzero width; it is {}", rect1.width); + } +} +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt index c891d9342..5c67e0b06 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt @@ -1,18 +1,22 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) -error[E0277]: `Rectangle` doesn't implement `std::fmt::Debug` + Compiling rectangles v0.1.0 (file:///projects/rectangles) +error[E0277]: `Rectangle` doesn't implement `Debug` +(エラー: `Rectangle`は`Debug`を実装していません) --> src/main.rs:12:31 | 12 | println!("rect1 is {:?}", rect1); | ^^^^^ `Rectangle` cannot be formatted using `{:?}` | - = help: the trait `std::fmt::Debug` is not implemented for `Rectangle` - = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug` - = note: required by `std::fmt::Debug::fmt` - -error: aborting due to previous error + = help: the trait `Debug` is not implemented for `Rectangle` + = note: add `#[derive(Debug)]` to `Rectangle` or manually `impl Debug for Rectangle` + (ヘルプ: トレイト`Debug`は`Rectangle`に対して実装されていません) + (注釈: `Rectangle`に`#[derive(Debug)]`を追加するか、手動で`impl Debug for Rectangle`してください) + = 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 annotating `Rectangle` with `#[derive(Debug)]` + | +1 + #[derive(Debug)] +2 | struct Rectangle { + | For more information about this error, try `rustc --explain E0277`. -error: could not compile `structs`. - -To learn more, run the command again with --verbose. +error: could not compile `rectangles` (bin "rectangles") due to 1 previous error diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt index 099ef9eac..db6deed9b 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt @@ -1,7 +1,7 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) + Compiling rectangles v0.1.0 (file:///projects/rectangles) Finished dev [unoptimized + debuginfo] target(s) in 0.48s - Running `target/debug/structs` + Running `target/debug/rectangles` rect1 is Rectangle { width: 30, height: 50, diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs b/listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs index 3ba384fba..ac134534e 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs @@ -1,9 +1,9 @@ // ANCHOR: here -#[derive(Debug)] // so we can inspect the state in a minute +#[derive(Debug)] // すぐに州を検査できるように enum UsState { Alabama, Alaska, - // --snip-- + // --略-- } enum Coin { diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs b/listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs index 222d54552..dc2bffb91 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs @@ -1,8 +1,8 @@ fn main() { // ANCHOR: here - let some_u8_value = Some(0u8); - match some_u8_value { - Some(3) => println!("three"), + let config_max = Some(3u8); + match config_max { + Some(max) => println!("The maximum is configured to be {}", max), _ => (), } // ANCHOR_END: here diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs index df451be8b..182221bf0 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs @@ -1,11 +1,11 @@ // ANCHOR: here -struct QuitMessage; // unit struct +struct QuitMessage; // ユニット構造体 struct MoveMessage { x: i32, y: i32, } -struct WriteMessage(String); // tuple struct -struct ChangeColorMessage(i32, i32, i32); // tuple struct +struct WriteMessage(String); // タプル構造体 +struct ChangeColorMessage(i32, i32, i32); // タプル構造体 // ANCHOR_END: here fn main() {} diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs index 66e0b6da1..2395b0e6d 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs @@ -9,7 +9,7 @@ fn main() { // ANCHOR: here impl Message { fn call(&self) { - // method body would be defined here + // メソッド本体はここで定義されます } } diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs index 9de5791b4..be552bfa5 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs @@ -1,7 +1,7 @@ fn main() { // ANCHOR: here let some_number = Some(5); - let some_string = Some("a string"); + let some_char = Some('e'); let absent_number: Option = None; // ANCHOR_END: here diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt index d3092d9fb..2f0596aaf 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt +++ b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt @@ -1,16 +1,21 @@ $ cargo run Compiling enums v0.1.0 (file:///projects/enums) -error[E0277]: cannot add `std::option::Option` to `i8` +error[E0277]: cannot add `Option` to `i8` +(エラー: `Option`を`i8`に足すことはできません) --> src/main.rs:5:17 | 5 | let sum = x + y; - | ^ no implementation for `i8 + std::option::Option` + | ^ no implementation for `i8 + Option` + (`i8 + `Option`のための実装がありません) | - = help: the trait `std::ops::Add>` is not implemented for `i8` - -error: aborting due to previous error + = help: the trait `Add>` is not implemented for `i8` + (ヘルプ: トレイト`Add`が`i8`に対して実装されていません) + = help: the following other types implement trait `Add`: + (ヘルプ: 以下の型であればトレイト`Add`を実装しています:) + + > + <&'a i8 as Add> + <&i8 as Add<&i8>> For more information about this error, try `rustc --explain E0277`. -error: could not compile `enums`. - -To learn more, run the command again with --verbose. +error: could not compile `enums` (bin "enums") due to 1 previous error diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt index da9e9d9bf..fa6e843fa 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt +++ b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt @@ -1,16 +1,25 @@ $ cargo run Compiling enums v0.1.0 (file:///projects/enums) error[E0004]: non-exhaustive patterns: `None` not covered +(エラー: 包括的でないパターン: `None`が網羅されていません) --> src/main.rs:3:15 | 3 | match x { | ^ pattern `None` not covered + (パターン`None`が網羅されていません) + | +note: `Option` defined here + --> /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/option.rs:570:1 + ::: /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/option.rs:574:5 + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown +(ヘルプ: ワイルドカードパターンか、以下に示すように明示的なパターンを持つアームを追加することで、すべての可能な場合が確実に処理されるようにしてください) + | +4 ~ Some(i) => Some(i + 1), +5 ~ None => todo!(), | - = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms - -error: aborting due to previous error For more information about this error, try `rustc --explain E0004`. -error: could not compile `enums`. - -To learn more, run the command again with --verbose. +error: could not compile `enums` (bin "enums") due to 1 previous error diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs deleted file mode 100644 index 6fc8ab058..000000000 --- a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn main() { - // ANCHOR: here - let some_u8_value = 0u8; - match some_u8_value { - 1 => println!("one"), - 3 => println!("three"), - 5 => println!("five"), - 7 => println!("seven"), - _ => (), - } - // ANCHOR_END: here -} diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs index fb6578cf6..735086d4e 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs @@ -1,8 +1,8 @@ fn main() { - let some_u8_value = Some(0u8); // ANCHOR: here - if let Some(3) = some_u8_value { - println!("three"); + let config_max = Some(3u8); + if let Some(max) = config_max { + println!("The maximum is configured to be {}", max); } // ANCHOR_END: here } diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs index 12c4c0fec..ac721ba43 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs @@ -2,7 +2,7 @@ enum UsState { Alabama, Alaska, - // --snip-- + // --略-- } enum Coin { diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs index ba7eda27b..1d145c272 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs @@ -2,7 +2,7 @@ enum UsState { Alabama, Alaska, - // --snip-- + // --略-- } enum Coin { diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.lock b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.lock similarity index 100% rename from listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.lock rename to listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.lock diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml similarity index 50% rename from listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.toml rename to listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs new file mode 100644 index 000000000..6ce0b5998 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs @@ -0,0 +1,14 @@ +fn main() { + // ANCHOR: here + let dice_roll = 9; + match dice_roll { + 3 => add_fancy_hat(), + 7 => remove_fancy_hat(), + other => move_player(other), + } + + fn add_fancy_hat() {} + fn remove_fancy_hat() {} + fn move_player(num_spaces: u8) {} + // ANCHOR_END: here +} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.lock b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.lock similarity index 86% rename from listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.lock rename to listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.lock index 2aa4918e5..f62e8ac45 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.lock +++ b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "ownership" +name = "enums" version = "0.1.0" diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml new file mode 100644 index 000000000..e959295f9 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "enums" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs new file mode 100644 index 000000000..586e23751 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs @@ -0,0 +1,14 @@ +fn main() { + // ANCHOR: here + let dice_roll = 9; + match dice_roll { + 3 => add_fancy_hat(), + 7 => remove_fancy_hat(), + _ => reroll(), + } + + fn add_fancy_hat() {} + fn remove_fancy_hat() {} + fn reroll() {} + // ANCHOR_END: here +} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.lock b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.lock similarity index 86% rename from listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.lock rename to listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.lock index e8007a19b..f62e8ac45 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.lock +++ b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "chapter10" +name = "enums" version = "0.1.0" diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml new file mode 100644 index 000000000..e959295f9 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "enums" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs new file mode 100644 index 000000000..e791742ee --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs @@ -0,0 +1,13 @@ +fn main() { + // ANCHOR: here + let dice_roll = 9; + match dice_roll { + 3 => add_fancy_hat(), + 7 => remove_fancy_hat(), + _ => (), + } + + fn add_fancy_hat() {} + fn remove_fancy_hat() {} + // ANCHOR_END: here +} diff --git a/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs index 0e40be70d..591e24557 100644 --- a/listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { mod hosting { fn add_to_waitlist() {} @@ -14,6 +13,3 @@ mod front_of_house { fn take_payment() {} } } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-03/output.txt b/listings/ch07-managing-growing-projects/listing-07-03/output.txt index 2a494c29e..2d06c7fd1 100644 --- a/listings/ch07-managing-growing-projects/listing-07-03/output.txt +++ b/listings/ch07-managing-growing-projects/listing-07-03/output.txt @@ -4,17 +4,29 @@ error[E0603]: module `hosting` is private --> src/lib.rs:9:28 | 9 | crate::front_of_house::hosting::add_to_waitlist(); - | ^^^^^^^ + | ^^^^^^^ --------------- 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 { + | ^^^^^^^^^^^ error[E0603]: module `hosting` is private --> src/lib.rs:12:21 | 12 | front_of_house::hosting::add_to_waitlist(); - | ^^^^^^^ - -error: aborting due to 2 previous errors + | ^^^^^^^ --------------- 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`. - -To learn more, run the command again with --verbose. +error: could not compile `restaurant` (lib) due to 2 previous errors diff --git a/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-05/output.txt b/listings/ch07-managing-growing-projects/listing-07-05/output.txt index 664c6a480..98d8d6e2a 100644 --- a/listings/ch07-managing-growing-projects/listing-07-05/output.txt +++ b/listings/ch07-managing-growing-projects/listing-07-05/output.txt @@ -4,17 +4,25 @@ error[E0603]: function `add_to_waitlist` is private --> src/lib.rs:9:37 | 9 | crate::front_of_house::hosting::add_to_waitlist(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ private function + | +note: the function `add_to_waitlist` is defined here + --> src/lib.rs:3:9 + | +3 | fn add_to_waitlist() {} + | ^^^^^^^^^^^^^^^^^^^^ error[E0603]: function `add_to_waitlist` is private --> src/lib.rs:12:30 | 12 | front_of_house::hosting::add_to_waitlist(); - | ^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors + | ^^^^^^^^^^^^^^^ private function + | +note: the function `add_to_waitlist` is defined here + --> src/lib.rs:3:9 + | +3 | fn add_to_waitlist() {} + | ^^^^^^^^^^^^^^^^^^^^ For more information about this error, try `rustc --explain E0603`. -error: could not compile `restaurant`. - -To learn more, run the command again with --verbose. +error: could not compile `restaurant` (lib) due to 2 previous errors diff --git a/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs index 74788f6cf..1e7c8b03c 100644 --- a/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} @@ -14,6 +13,3 @@ pub fn eat_at_restaurant() { // 相対パス front_of_house::hosting::add_to_waitlist(); } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs index a789379ae..b3ddb4f0f 100644 --- a/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs @@ -1,14 +1,10 @@ -// ANCHOR: here -fn serve_order() {} +fn deliver_order() {} mod back_of_house { fn fix_incorrect_order() { cook_order(); - super::serve_order(); + super::deliver_order(); } fn cook_order() {} } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs index 3a7568375..cf31a9c97 100644 --- a/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} @@ -9,9 +8,4 @@ use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-12/output.txt b/listings/ch07-managing-growing-projects/listing-07-12/output.txt new file mode 100644 index 000000000..ae7425abc --- /dev/null +++ b/listings/ch07-managing-growing-projects/listing-07-12/output.txt @@ -0,0 +1,28 @@ +$ cargo build + Compiling restaurant v0.1.0 (file:///projects/restaurant) +error[E0433]: failed to resolve: use of undeclared crate or module `hosting` +(エラー: 名前解決に失敗しました: 宣言されていないクレートまたはモジュール`hosting`の使用) + --> src/lib.rs:11:9 + | +11 | hosting::add_to_waitlist(); + | ^^^^^^^ use of undeclared crate or module `hosting` + | (宣言されていないクレートまたはモジュール`hosting`の使用) + | +help: consider importing this module through its public re-export +(ヘルプ: 公開再エクスポートからこのモジュールをインポートすることを検討してください) + | +10 + use crate::hosting; + | + +warning: unused import: `crate::front_of_house::hosting` +(警告: 未使用のインポート: `crate::front_of_house::hosting`) + --> src/lib.rs:7:5 + | +7 | use 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 diff --git a/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs index 6b0101b7d..afc759423 100644 --- a/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs @@ -1,17 +1,13 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } -use self::front_of_house::hosting; +use crate::front_of_house::hosting; -pub fn eat_at_restaurant() { - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); +mod customer { + pub fn eat_at_restaurant() { + hosting::add_to_waitlist(); + } } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs index 98414aac9..c72994efe 100644 --- a/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} @@ -9,9 +8,4 @@ use crate::front_of_house::hosting::add_to_waitlist; pub fn eat_at_restaurant() { add_to_waitlist(); - add_to_waitlist(); - add_to_waitlist(); } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs index e948d7c38..45cf1bac9 100644 --- a/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} @@ -9,9 +8,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock index c346748e5..2ae9e459e 100644 --- a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock +++ b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock @@ -1,87 +1,75 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "bitflags" -version = "1.2.1" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "getrandom" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "guessing_game" version = "0.1.0" dependencies = [ - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand", ] [[package]] name = "libc" -version = "0.2.53" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.5.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "rand_core" -version = "0.3.1" +name = "rand_chacha" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", + "rand_core", ] [[package]] name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)" = "ec350a9417dfd244dc9a6c4a71e13895a4db6b92f0b106f07ebbc3f3bc580cee" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml index ad5ca696d..d508e9578 100644 --- a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] -rand = "0.5.5" +rand = "0.8.5" diff --git a/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs b/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs index 233198a58..7eda7322f 100644 --- a/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs +++ b/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs @@ -10,9 +10,9 @@ use std::{cmp::Ordering, io}; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1, 101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -24,7 +24,7 @@ fn main() { let guess: u32 = guess.trim().parse().expect("Please type a number!"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs index 065b1b804..d6769556a 100644 --- a/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs @@ -4,6 +4,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock index 2b3d41ad6..2ae9e459e 100644 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock @@ -1,87 +1,75 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "bitflags" -version = "1.2.0" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "getrandom" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "guessing_game" version = "0.1.0" dependencies = [ - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand", ] [[package]] name = "libc" -version = "0.2.51" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.5.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "rand_core" -version = "0.3.1" +name = "rand_chacha" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", + "rand_core", ] [[package]] name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml index 10932024b..7eda67aea 100644 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml @@ -1,10 +1,9 @@ [package] name = "guessing_game" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.5.5" +rand = "0.8.5" diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs index c46464ec2..ecea756fa 100644 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs @@ -11,9 +11,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1, 101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -23,7 +23,7 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml +++ b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs index 065b1b804..d6769556a 100644 --- a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs +++ b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs @@ -4,6 +4,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.lock b/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.lock new file mode 100644 index 000000000..4773c201d --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "backyard" +version = "0.1.0" diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.toml b/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.toml new file mode 100644 index 000000000..6e904abbe --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "backyard" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/output.txt b/listings/ch07-managing-growing-projects/quick-reference-example/output.txt new file mode 100644 index 000000000..e36a45eb0 --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/output.txt @@ -0,0 +1,5 @@ +$ cargo run + Compiling backyard v0.1.0 (file:///projects/backyard) + Finished dev [unoptimized + debuginfo] target(s) in 0.36s + Running `target/debug/backyard` +I'm growing Asparagus! diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs b/listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs new file mode 100644 index 000000000..6c7f9b1cb --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs @@ -0,0 +1 @@ +pub mod vegetables; diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs b/listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs new file mode 100644 index 000000000..b00f785ef --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct Asparagus {} diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs b/listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs new file mode 100644 index 000000000..7a024a9a0 --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs @@ -0,0 +1,8 @@ +use crate::garden::vegetables::Asparagus; + +pub mod garden; + +fn main() { + let plant = Asparagus {}; + println!("I'm growing {:?}!", plant); +} diff --git a/listings/ch08-common-collections/listing-08-01/Cargo.toml b/listings/ch08-common-collections/listing-08-01/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-01/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-02/Cargo.toml b/listings/ch08-common-collections/listing-08-02/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-02/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-03/Cargo.toml b/listings/ch08-common-collections/listing-08-03/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-03/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-04/Cargo.toml b/listings/ch08-common-collections/listing-08-04/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-04/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-04/src/main.rs b/listings/ch08-common-collections/listing-08-04/src/main.rs index bae2b87e0..8dc674de9 100644 --- a/listings/ch08-common-collections/listing-08-04/src/main.rs +++ b/listings/ch08-common-collections/listing-08-04/src/main.rs @@ -1,9 +1,17 @@ fn main() { // ANCHOR: here - { - let v = vec![1, 2, 3, 4]; + let v = vec![1, 2, 3, 4, 5]; - // vで作業をする - } // <- vはここでスコープを抜け、解放される - // ANCHOR_END: here + let third: &i32 = &v[2]; + // "3つ目の要素は{third}です" + println!("The third element is {third}"); + + let third: Option<&i32> = v.get(2); + match third { + // "3つ目の要素は{third}です" + Some(third) => println!("The third element is {third}"), + // "3つ目の要素はありません。" + None => println!("There is no third element."), + } + // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-05/Cargo.toml b/listings/ch08-common-collections/listing-08-05/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-05/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-05/src/main.rs b/listings/ch08-common-collections/listing-08-05/src/main.rs index 185ed8eae..783d9b110 100644 --- a/listings/ch08-common-collections/listing-08-05/src/main.rs +++ b/listings/ch08-common-collections/listing-08-05/src/main.rs @@ -2,14 +2,7 @@ fn main() { // ANCHOR: here let v = vec![1, 2, 3, 4, 5]; - let third: &i32 = &v[2]; - println!("The third element is {}", third); - - match v.get(2) { - // "3つ目の要素は{}です" - Some(third) => println!("The third element is {}", third), - // "3つ目の要素はありません。" - None => println!("There is no third element."), - } + let does_not_exist = &v[100]; + let does_not_exist = v.get(100); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-06/Cargo.toml b/listings/ch08-common-collections/listing-08-06/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-06/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-07/output.txt b/listings/ch08-common-collections/listing-08-06/output.txt similarity index 61% rename from listings/ch08-common-collections/listing-08-07/output.txt rename to listings/ch08-common-collections/listing-08-06/output.txt index a46e34ee7..4bdfb3152 100644 --- a/listings/ch08-common-collections/listing-08-07/output.txt +++ b/listings/ch08-common-collections/listing-08-06/output.txt @@ -7,18 +7,14 @@ error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immuta 4 | let first = &v[0]; | - immutable borrow occurs here | (不変借用はここで発生しています) -5 | +5 | 6 | v.push(6); | ^^^^^^^^^ mutable borrow occurs here | (可変借用はここで発生しています) -7 | -8 | println!("The first element is: {}", first); - | ----- immutable borrow later used here - | (その後、不変借用はここで使われています) - -error: aborting due to previous error +7 | +8 | println!("The first element is: {first}"); + | ------- immutable borrow later used here + | (その後、不変借用はここで使われています) For more information about this error, try `rustc --explain E0502`. -error: could not compile `collections`. - -To learn more, run the command again with --verbose. +error: could not compile `collections` (bin "collections") due to 1 previous error diff --git a/listings/ch08-common-collections/listing-08-06/src/main.rs b/listings/ch08-common-collections/listing-08-06/src/main.rs index 783d9b110..b84d49e52 100644 --- a/listings/ch08-common-collections/listing-08-06/src/main.rs +++ b/listings/ch08-common-collections/listing-08-06/src/main.rs @@ -1,8 +1,12 @@ fn main() { // ANCHOR: here - let v = vec![1, 2, 3, 4, 5]; + let mut v = vec![1, 2, 3, 4, 5]; - let does_not_exist = &v[100]; - let does_not_exist = v.get(100); + let first = &v[0]; + + v.push(6); + + // "最初の要素は: {first}" + println!("The first element is: {first}"); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-07/Cargo.toml b/listings/ch08-common-collections/listing-08-07/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-07/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-07/src/main.rs b/listings/ch08-common-collections/listing-08-07/src/main.rs index 1b42274a6..aebf855a9 100644 --- a/listings/ch08-common-collections/listing-08-07/src/main.rs +++ b/listings/ch08-common-collections/listing-08-07/src/main.rs @@ -1,11 +1,8 @@ fn main() { // ANCHOR: here - let mut v = vec![1, 2, 3, 4, 5]; - - let first = &v[0]; - - v.push(6); - - println!("The first element is: {}", first); + let v = vec![100, 32, 57]; + for i in &v { + println!("{i}"); + } // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-08/Cargo.toml b/listings/ch08-common-collections/listing-08-08/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-08/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-08/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-08/src/main.rs b/listings/ch08-common-collections/listing-08-08/src/main.rs index 38b97784b..c62ba21b4 100644 --- a/listings/ch08-common-collections/listing-08-08/src/main.rs +++ b/listings/ch08-common-collections/listing-08-08/src/main.rs @@ -1,8 +1,8 @@ fn main() { // ANCHOR: here - let v = vec![100, 32, 57]; - for i in &v { - println!("{}", i); + let mut v = vec![100, 32, 57]; + for i in &mut v { + *i += 50; } // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-09/Cargo.toml b/listings/ch08-common-collections/listing-08-09/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-09/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-09/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-09/src/main.rs b/listings/ch08-common-collections/listing-08-09/src/main.rs index c62ba21b4..c2198883b 100644 --- a/listings/ch08-common-collections/listing-08-09/src/main.rs +++ b/listings/ch08-common-collections/listing-08-09/src/main.rs @@ -1,8 +1,15 @@ fn main() { // ANCHOR: here - let mut v = vec![100, 32, 57]; - for i in &mut v { - *i += 50; + enum SpreadsheetCell { + Int(i32), + Float(f64), + Text(String), } + + let row = vec![ + SpreadsheetCell::Int(3), + SpreadsheetCell::Text(String::from("blue")), + SpreadsheetCell::Float(10.12), + ]; // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-10/Cargo.toml b/listings/ch08-common-collections/listing-08-10/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-10/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-10/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-10/src/main.rs b/listings/ch08-common-collections/listing-08-10/src/main.rs index c2198883b..bae2b87e0 100644 --- a/listings/ch08-common-collections/listing-08-10/src/main.rs +++ b/listings/ch08-common-collections/listing-08-10/src/main.rs @@ -1,15 +1,9 @@ fn main() { // ANCHOR: here - enum SpreadsheetCell { - Int(i32), - Float(f64), - Text(String), - } + { + let v = vec![1, 2, 3, 4]; - let row = vec![ - SpreadsheetCell::Int(3), - SpreadsheetCell::Text(String::from("blue")), - SpreadsheetCell::Float(10.12), - ]; - // ANCHOR_END: here + // vで作業をする + } // <- vはここでスコープを抜け、解放される + // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-11/Cargo.toml b/listings/ch08-common-collections/listing-08-11/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-11/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-11/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-12/Cargo.toml b/listings/ch08-common-collections/listing-08-12/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-12/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-12/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-13/Cargo.toml b/listings/ch08-common-collections/listing-08-13/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-13/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-13/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-14/Cargo.toml b/listings/ch08-common-collections/listing-08-14/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-14/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-14/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-15/Cargo.toml b/listings/ch08-common-collections/listing-08-15/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-15/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-15/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-16/Cargo.toml b/listings/ch08-common-collections/listing-08-16/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-16/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-16/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-16/src/main.rs b/listings/ch08-common-collections/listing-08-16/src/main.rs index 8938dc143..db57cddba 100644 --- a/listings/ch08-common-collections/listing-08-16/src/main.rs +++ b/listings/ch08-common-collections/listing-08-16/src/main.rs @@ -3,6 +3,6 @@ fn main() { let mut s1 = String::from("foo"); let s2 = "bar"; s1.push_str(s2); - println!("s2 is {}", s2); + println!("s2 is {s2}"); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-17/Cargo.toml b/listings/ch08-common-collections/listing-08-17/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-17/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-17/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-18/Cargo.toml b/listings/ch08-common-collections/listing-08-18/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-18/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-18/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-18/src/main.rs b/listings/ch08-common-collections/listing-08-18/src/main.rs index 93939a69f..1b01c3990 100644 --- a/listings/ch08-common-collections/listing-08-18/src/main.rs +++ b/listings/ch08-common-collections/listing-08-18/src/main.rs @@ -2,6 +2,6 @@ fn main() { // ANCHOR: here let s1 = String::from("Hello, "); let s2 = String::from("world!"); - let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used + let s3 = s1 + &s2; // s1はムーブされ、もう使用できないことに注意 // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-19/Cargo.toml b/listings/ch08-common-collections/listing-08-19/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-19/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-19/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-19/output.txt b/listings/ch08-common-collections/listing-08-19/output.txt index c239f7189..2553303df 100644 --- a/listings/ch08-common-collections/listing-08-19/output.txt +++ b/listings/ch08-common-collections/listing-08-19/output.txt @@ -1,16 +1,23 @@ $ cargo run Compiling collections v0.1.0 (file:///projects/collections) -error[E0277]: the type `std::string::String` cannot be indexed by `{integer}` - --> src/main.rs:3:13 +error[E0277]: the type `String` cannot be indexed by `{integer}` +(エラー: 型`String`は`{Integer}`で添え字アクセスできませんん) + --> src/main.rs:3:16 | 3 | let h = s1[0]; - | ^^^^^ `std::string::String` cannot be indexed by `{integer}` + | ^ `String` cannot be indexed by `{integer}` + | (`String`は`{Integer}`で添え字アクセスできません) | - = help: the trait `std::ops::Index<{integer}>` is not implemented for `std::string::String` - -error: aborting due to previous error + = help: the trait `Index<{integer}>` is not implemented for `String` + (ヘルプ: `Index<{Integer}>`というトレイトが`String`に対して実装されていません) + = help: the following other types implement trait `Index`: + (ヘルプ: 以下の型であればトレイト`Index`を実装しています:) + > + >> + >> + >> + >> + >> For more information about this error, try `rustc --explain E0277`. -error: could not compile `collections`. - -To learn more, run the command again with --verbose. +error: could not compile `collections` (bin "collections") due to 1 previous error diff --git a/listings/ch08-common-collections/listing-08-20/Cargo.toml b/listings/ch08-common-collections/listing-08-20/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-20/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-20/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-21/Cargo.toml b/listings/ch08-common-collections/listing-08-21/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-21/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-21/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-21/src/main.rs b/listings/ch08-common-collections/listing-08-21/src/main.rs index 0ebd20d4e..07551549d 100644 --- a/listings/ch08-common-collections/listing-08-21/src/main.rs +++ b/listings/ch08-common-collections/listing-08-21/src/main.rs @@ -2,10 +2,12 @@ fn main() { // ANCHOR: here use std::collections::HashMap; - let teams = vec![String::from("Blue"), String::from("Yellow")]; - let initial_scores = vec![10, 50]; + let mut scores = HashMap::new(); - let mut scores: HashMap<_, _> = - teams.into_iter().zip(initial_scores.into_iter()).collect(); + scores.insert(String::from("Blue"), 10); + scores.insert(String::from("Yellow"), 50); + + let team_name = String::from("Blue"); + let score = scores.get(&team_name).copied().unwrap_or(0); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-22/Cargo.toml b/listings/ch08-common-collections/listing-08-22/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-22/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-22/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-22/src/main.rs b/listings/ch08-common-collections/listing-08-22/src/main.rs index 2b2a73f94..647538c80 100644 --- a/listings/ch08-common-collections/listing-08-22/src/main.rs +++ b/listings/ch08-common-collections/listing-08-22/src/main.rs @@ -9,5 +9,7 @@ fn main() { map.insert(field_name, field_value); // field_name and field_value are invalid at this point, try using them and // see what compiler error you get! + // field_nameとfield_valueはこの時点で無効になる。試しに使ってみて + // どんなコンパイルエラーが出るか確認してみて! // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-23/Cargo.toml b/listings/ch08-common-collections/listing-08-23/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-23/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-23/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-23/src/main.rs b/listings/ch08-common-collections/listing-08-23/src/main.rs index 508e33cbb..e8684cf2b 100644 --- a/listings/ch08-common-collections/listing-08-23/src/main.rs +++ b/listings/ch08-common-collections/listing-08-23/src/main.rs @@ -5,9 +5,8 @@ fn main() { let mut scores = HashMap::new(); scores.insert(String::from("Blue"), 10); - scores.insert(String::from("Yellow"), 50); + scores.insert(String::from("Blue"), 25); - let team_name = String::from("Blue"); - let score = scores.get(&team_name); + println!("{:?}", scores); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-24/Cargo.toml b/listings/ch08-common-collections/listing-08-24/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-24/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-24/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-24/src/main.rs b/listings/ch08-common-collections/listing-08-24/src/main.rs index e8684cf2b..3ad97b57a 100644 --- a/listings/ch08-common-collections/listing-08-24/src/main.rs +++ b/listings/ch08-common-collections/listing-08-24/src/main.rs @@ -3,9 +3,10 @@ fn main() { use std::collections::HashMap; let mut scores = HashMap::new(); - scores.insert(String::from("Blue"), 10); - scores.insert(String::from("Blue"), 25); + + scores.entry(String::from("Yellow")).or_insert(50); + scores.entry(String::from("Blue")).or_insert(50); println!("{:?}", scores); // ANCHOR_END: here diff --git a/listings/ch08-common-collections/listing-08-25/Cargo.toml b/listings/ch08-common-collections/listing-08-25/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/listing-08-25/Cargo.toml +++ b/listings/ch08-common-collections/listing-08-25/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/listing-08-25/src/main.rs b/listings/ch08-common-collections/listing-08-25/src/main.rs index 3ad97b57a..f3f6aa166 100644 --- a/listings/ch08-common-collections/listing-08-25/src/main.rs +++ b/listings/ch08-common-collections/listing-08-25/src/main.rs @@ -2,12 +2,15 @@ fn main() { // ANCHOR: here use std::collections::HashMap; - let mut scores = HashMap::new(); - scores.insert(String::from("Blue"), 10); + let text = "hello world wonderful world"; - scores.entry(String::from("Yellow")).or_insert(50); - scores.entry(String::from("Blue")).or_insert(50); + let mut map = HashMap::new(); - println!("{:?}", scores); + for word in text.split_whitespace() { + let count = map.entry(word).or_insert(0); + *count += 1; + } + + println!("{:?}", map); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/listing-08-26/Cargo.toml b/listings/ch08-common-collections/listing-08-26/Cargo.toml deleted file mode 100644 index b36871bec..000000000 --- a/listings/ch08-common-collections/listing-08-26/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "collections" -version = "0.1.0" -authors = ["Your Name "] -edition = "2018" - -[dependencies] diff --git a/listings/ch08-common-collections/listing-08-26/src/main.rs b/listings/ch08-common-collections/listing-08-26/src/main.rs deleted file mode 100644 index f3f6aa166..000000000 --- a/listings/ch08-common-collections/listing-08-26/src/main.rs +++ /dev/null @@ -1,16 +0,0 @@ -fn main() { - // ANCHOR: here - use std::collections::HashMap; - - let text = "hello world wonderful world"; - - let mut map = HashMap::new(); - - for word in text.split_whitespace() { - let count = map.entry(word).or_insert(0); - *count += 1; - } - - println!("{:?}", map); - // ANCHOR_END: here -} diff --git a/listings/ch08-common-collections/no-listing-01-concat-multiple-strings/Cargo.toml b/listings/ch08-common-collections/no-listing-01-concat-multiple-strings/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/no-listing-01-concat-multiple-strings/Cargo.toml +++ b/listings/ch08-common-collections/no-listing-01-concat-multiple-strings/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/no-listing-02-format/Cargo.toml b/listings/ch08-common-collections/no-listing-02-format/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/no-listing-02-format/Cargo.toml +++ b/listings/ch08-common-collections/no-listing-02-format/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/no-listing-02-format/src/main.rs b/listings/ch08-common-collections/no-listing-02-format/src/main.rs index 4a38e63d2..db408e2b7 100644 --- a/listings/ch08-common-collections/no-listing-02-format/src/main.rs +++ b/listings/ch08-common-collections/no-listing-02-format/src/main.rs @@ -4,6 +4,6 @@ fn main() { let s2 = String::from("tac"); let s3 = String::from("toe"); - let s = format!("{}-{}-{}", s1, s2, s3); + let s = format!("{s1}-{s2}-{s3}"); // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/Cargo.toml b/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/Cargo.toml +++ b/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs b/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs index 2e7dc02e6..bb13c86f1 100644 --- a/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs +++ b/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs @@ -8,7 +8,7 @@ fn main() { scores.insert(String::from("Yellow"), 50); for (key, value) in &scores { - println!("{}: {}", key, value); + println!("{key}: {value}"); } // ANCHOR_END: here } diff --git a/listings/ch08-common-collections/output-only-01-not-char-boundary/Cargo.toml b/listings/ch08-common-collections/output-only-01-not-char-boundary/Cargo.toml index b36871bec..fe4959823 100644 --- a/listings/ch08-common-collections/output-only-01-not-char-boundary/Cargo.toml +++ b/listings/ch08-common-collections/output-only-01-not-char-boundary/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "collections" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch08-common-collections/output-only-01-not-char-boundary/output.txt b/listings/ch08-common-collections/output-only-01-not-char-boundary/output.txt index e05d33233..52263e818 100644 --- a/listings/ch08-common-collections/output-only-01-not-char-boundary/output.txt +++ b/listings/ch08-common-collections/output-only-01-not-char-boundary/output.txt @@ -2,5 +2,8 @@ $ cargo run Compiling collections v0.1.0 (file:///projects/collections) Finished dev [unoptimized + debuginfo] target(s) in 0.43s Running `target/debug/collections` -thread 'main' panicked at 'byte index 1 is not a char boundary; it is inside 'З' (bytes 0..2) of `Здравствуйте`', src/libcore/str/mod.rs:2069:5 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. +thread 'main' panicked at src/main.rs:4:19: +byte index 1 is not a char boundary; it is inside 'З' (bytes 0..2) of `Здравствуйте` +('main'スレッドはsrc/main:4:19でパニックしました: +バイト添え字1は文字の境界ではありません; `Здравствуйте`の'З'(バイト0..2)の中です) +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/listings/ch09-error-handling/listing-09-01/Cargo.toml b/listings/ch09-error-handling/listing-09-01/Cargo.toml index 310342cd3..660e2c819 100644 --- a/listings/ch09-error-handling/listing-09-01/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "panic" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-01/output.txt b/listings/ch09-error-handling/listing-09-01/output.txt index 36aef5049..192859280 100644 --- a/listings/ch09-error-handling/listing-09-01/output.txt +++ b/listings/ch09-error-handling/listing-09-01/output.txt @@ -2,5 +2,8 @@ $ cargo run Compiling panic v0.1.0 (file:///projects/panic) Finished dev [unoptimized + debuginfo] target(s) in 0.27s Running `target/debug/panic` -thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', /rustc/5e1a799842ba6ed4a57e91f7ab9435947482f7d8/src/libcore/slice/mod.rs:2806:10 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. +thread 'main' panicked at src/main.rs:4:6: +index out of bounds: the len is 3 but the index is 99 +('main'スレッドはsrc/main.rs:4:6でパニックしました: +境界外番号: 長さは3なのに、添え字は99です) +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/listings/ch09-error-handling/listing-09-03/Cargo.toml b/listings/ch09-error-handling/listing-09-03/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/listing-09-03/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-03/src/main.rs b/listings/ch09-error-handling/listing-09-03/src/main.rs index 0dfd10b5e..2342904ed 100644 --- a/listings/ch09-error-handling/listing-09-03/src/main.rs +++ b/listings/ch09-error-handling/listing-09-03/src/main.rs @@ -1,5 +1,5 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt"); + let greeting_file_result = File::open("hello.txt"); } diff --git a/listings/ch09-error-handling/listing-09-04/Cargo.toml b/listings/ch09-error-handling/listing-09-04/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/listing-09-04/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-04/output.txt b/listings/ch09-error-handling/listing-09-04/output.txt index acc4f0c74..3e41d1f52 100644 --- a/listings/ch09-error-handling/listing-09-04/output.txt +++ b/listings/ch09-error-handling/listing-09-04/output.txt @@ -2,5 +2,8 @@ $ cargo run Compiling error-handling v0.1.0 (file:///projects/error-handling) Finished dev [unoptimized + debuginfo] target(s) in 0.73s Running `target/debug/error-handling` -thread 'main' panicked at 'Problem opening the file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:8:23 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. +thread 'main' panicked at src/main.rs:8:23: +Problem opening the file: Os { code: 2, kind: NotFound, message: "No such file or directory" } +('main'スレッドは、src/main.rs:8:23でパニックしました: +ファイルを開く際に問題がありました: Os { code: 2, kind: NotFound, message: "そのようなファイルやディレクトリはありません" }) +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/listings/ch09-error-handling/listing-09-04/src/main.rs b/listings/ch09-error-handling/listing-09-04/src/main.rs index 070fc3380..dc1ef3cdd 100644 --- a/listings/ch09-error-handling/listing-09-04/src/main.rs +++ b/listings/ch09-error-handling/listing-09-04/src/main.rs @@ -1,10 +1,11 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt"); + let greeting_file_result = File::open("hello.txt"); - let f = match f { + let greeting_file = match greeting_file_result { Ok(file) => file, + // "ファイルを開くのに問題がありました: {:?}" Err(error) => panic!("Problem opening the file: {:?}", error), }; } diff --git a/listings/ch09-error-handling/listing-09-05/Cargo.toml b/listings/ch09-error-handling/listing-09-05/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/listing-09-05/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-05/src/main.rs b/listings/ch09-error-handling/listing-09-05/src/main.rs index 8c4f773b9..25dac5c47 100644 --- a/listings/ch09-error-handling/listing-09-05/src/main.rs +++ b/listings/ch09-error-handling/listing-09-05/src/main.rs @@ -2,17 +2,19 @@ use std::fs::File; use std::io::ErrorKind; fn main() { - let f = File::open("hello.txt"); + let greeting_file_result = File::open("hello.txt"); - let f = match f { + let greeting_file = match greeting_file_result { Ok(file) => file, Err(error) => match error.kind() { ErrorKind::NotFound => match File::create("hello.txt") { Ok(fc) => fc, + // "ファイルを作成するのに問題がありました: {:?}" Err(e) => panic!("Problem creating the file: {:?}", e), }, other_error => { - panic!("Problem opening the file: {:?}", other_error) + // "ファイルを開くのに問題がありました: {:?}" + panic!("Problem opening the file: {:?}", other_error); } }, }; diff --git a/listings/ch09-error-handling/listing-09-06/Cargo.toml b/listings/ch09-error-handling/listing-09-06/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/listing-09-06/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-06/src/main.rs b/listings/ch09-error-handling/listing-09-06/src/main.rs index 437d858f4..a70734cb5 100644 --- a/listings/ch09-error-handling/listing-09-06/src/main.rs +++ b/listings/ch09-error-handling/listing-09-06/src/main.rs @@ -1,20 +1,19 @@ // ANCHOR: here use std::fs::File; -use std::io; -use std::io::Read; +use std::io::{self, Read}; fn read_username_from_file() -> Result { - let f = File::open("hello.txt"); + let username_file_result = File::open("hello.txt"); - let mut f = match f { + let mut username_file = match username_file_result { Ok(file) => file, Err(e) => return Err(e), }; - let mut s = String::new(); + let mut username = String::new(); - match f.read_to_string(&mut s) { - Ok(_) => Ok(s), + match username_file.read_to_string(&mut username) { + Ok(_) => Ok(username), Err(e) => Err(e), } } diff --git a/listings/ch09-error-handling/listing-09-07/Cargo.toml b/listings/ch09-error-handling/listing-09-07/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/listing-09-07/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-07/src/main.rs b/listings/ch09-error-handling/listing-09-07/src/main.rs index b9f6172cb..0295949d2 100644 --- a/listings/ch09-error-handling/listing-09-07/src/main.rs +++ b/listings/ch09-error-handling/listing-09-07/src/main.rs @@ -1,13 +1,12 @@ // ANCHOR: here use std::fs::File; -use std::io; -use std::io::Read; +use std::io::{self, Read}; fn read_username_from_file() -> Result { - let mut f = File::open("hello.txt")?; - let mut s = String::new(); - f.read_to_string(&mut s)?; - Ok(s) + let mut username_file = File::open("hello.txt")?; + let mut username = String::new(); + username_file.read_to_string(&mut username)?; + Ok(username) } // ANCHOR_END: here diff --git a/listings/ch09-error-handling/listing-09-08/Cargo.toml b/listings/ch09-error-handling/listing-09-08/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/listing-09-08/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-08/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-08/src/main.rs b/listings/ch09-error-handling/listing-09-08/src/main.rs index f36e4d021..ca672caad 100644 --- a/listings/ch09-error-handling/listing-09-08/src/main.rs +++ b/listings/ch09-error-handling/listing-09-08/src/main.rs @@ -1,14 +1,13 @@ // ANCHOR: here use std::fs::File; -use std::io; -use std::io::Read; +use std::io::{self, Read}; fn read_username_from_file() -> Result { - let mut s = String::new(); + let mut username = String::new(); - File::open("hello.txt")?.read_to_string(&mut s)?; + File::open("hello.txt")?.read_to_string(&mut username)?; - Ok(s) + Ok(username) } // ANCHOR_END: here diff --git a/listings/ch09-error-handling/listing-09-09/Cargo.toml b/listings/ch09-error-handling/listing-09-09/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/listing-09-09/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-09/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-10/Cargo.lock b/listings/ch09-error-handling/listing-09-10/Cargo.lock index c346748e5..1fa96b797 100644 --- a/listings/ch09-error-handling/listing-09-10/Cargo.lock +++ b/listings/ch09-error-handling/listing-09-10/Cargo.lock @@ -1,87 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "guessing_game" +name = "error-handling" version = "0.1.0" -dependencies = [ - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libc" -version = "0.2.53" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -[metadata] -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)" = "ec350a9417dfd244dc9a6c4a71e13895a4db6b92f0b106f07ebbc3f3bc580cee" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/listings/ch09-error-handling/listing-09-10/Cargo.toml b/listings/ch09-error-handling/listing-09-10/Cargo.toml index ad5ca696d..c496db783 100644 --- a/listings/ch09-error-handling/listing-09-10/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-10/Cargo.toml @@ -1,8 +1,6 @@ [package] -name = "guessing_game" +name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] -rand = "0.5.5" diff --git a/listings/ch09-error-handling/listing-09-10/output.txt b/listings/ch09-error-handling/listing-09-10/output.txt new file mode 100644 index 000000000..2ed180943 --- /dev/null +++ b/listings/ch09-error-handling/listing-09-10/output.txt @@ -0,0 +1,18 @@ +$ cargo run + Compiling error-handling v0.1.0 (file:///projects/error-handling) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) +(エラー: `?`演算子は`Result`または`Option`(あるいはその他`FromResidual`を実装する型)を返す関数内でのみ使用できます + --> src/main.rs:4:48 + | +3 | fn main() { + | --------- this function should return `Result` or `Option` to accept `?` + (`?`を使えるようにするには、この関数は`Result`または`Option`を返すべきです) +4 | let greeting_file = File::open("hello.txt")?; + | ^ cannot use the `?` operator in a function that returns `()` + (`()`を返す関数内では`?`演算子を使用できません) + | + = help: the trait `FromResidual>` is not implemented for `()` + (ヘルプ: トレイト`FromResidual>`は`()`に対して実装されていません) + +For more information about this error, try `rustc --explain E0277`. +error: could not compile `error-handling` (bin "error-handling") due to 1 previous error diff --git a/listings/ch09-error-handling/listing-09-10/src/main.rs b/listings/ch09-error-handling/listing-09-10/src/main.rs index 7448979a0..38b005480 100644 --- a/listings/ch09-error-handling/listing-09-10/src/main.rs +++ b/listings/ch09-error-handling/listing-09-10/src/main.rs @@ -1,55 +1,5 @@ -use rand::Rng; -use std::cmp::Ordering; -use std::io; - -// ANCHOR: here -pub struct Guess { - value: i32, -} - -impl Guess { - pub fn new(value: i32) -> Guess { - if value < 1 || value > 100 { - panic!("Guess value must be between 1 and 100, got {}.", value); - } - - Guess { value } - } - - pub fn value(&self) -> i32 { - self.value - } -} -// ANCHOR_END: here +use std::fs::File; fn main() { - println!("Guess the number!"); - - let secret_number = rand::thread_rng().gen_range(1, 101); - - loop { - println!("Please input your guess."); - - let mut guess = String::new(); - - io::stdin() - .read_line(&mut guess) - .expect("Failed to read line"); - - let guess: i32 = match guess.trim().parse() { - Ok(num) => num, - Err(_) => continue, - }; - - let guess = Guess::new(guess); - - match guess.value().cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => { - println!("You win!"); - break; - } - } - } + let greeting_file = File::open("hello.txt")?; } diff --git a/listings/ch09-error-handling/no-listing-03-closures/Cargo.lock b/listings/ch09-error-handling/listing-09-11/Cargo.lock similarity index 92% rename from listings/ch09-error-handling/no-listing-03-closures/Cargo.lock rename to listings/ch09-error-handling/listing-09-11/Cargo.lock index 1fa96b797..7320ae639 100644 --- a/listings/ch09-error-handling/no-listing-03-closures/Cargo.lock +++ b/listings/ch09-error-handling/listing-09-11/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "error-handling" version = "0.1.0" - diff --git a/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.toml b/listings/ch09-error-handling/listing-09-11/Cargo.toml similarity index 53% rename from listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.toml rename to listings/ch09-error-handling/listing-09-11/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/no-listing-07-main-returning-result/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-11/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/listing-09-11/src/main.rs b/listings/ch09-error-handling/listing-09-11/src/main.rs new file mode 100644 index 000000000..bd5322786 --- /dev/null +++ b/listings/ch09-error-handling/listing-09-11/src/main.rs @@ -0,0 +1,15 @@ +// ANCHOR: here +fn last_char_of_first_line(text: &str) -> Option { + text.lines().next()?.chars().last() +} +// ANCHOR_END: here + +fn main() { + assert_eq!( + last_char_of_first_line("Hello, world\nHow are you today?"), + Some('d') + ); + + assert_eq!(last_char_of_first_line(""), None); + assert_eq!(last_char_of_first_line("\nhi"), None); +} diff --git a/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.lock b/listings/ch09-error-handling/listing-09-12/Cargo.lock similarity index 100% rename from listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.lock rename to listings/ch09-error-handling/listing-09-12/Cargo.lock diff --git a/listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.toml b/listings/ch09-error-handling/listing-09-12/Cargo.toml similarity index 53% rename from listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.toml rename to listings/ch09-error-handling/listing-09-12/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/no-listing-06-question-mark-in-main/Cargo.toml +++ b/listings/ch09-error-handling/listing-09-12/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/no-listing-07-main-returning-result/src/main.rs b/listings/ch09-error-handling/listing-09-12/src/main.rs similarity index 66% rename from listings/ch09-error-handling/no-listing-07-main-returning-result/src/main.rs rename to listings/ch09-error-handling/listing-09-12/src/main.rs index 7f16b8e99..b0f7445f4 100644 --- a/listings/ch09-error-handling/no-listing-07-main-returning-result/src/main.rs +++ b/listings/ch09-error-handling/listing-09-12/src/main.rs @@ -2,7 +2,7 @@ use std::error::Error; use std::fs::File; fn main() -> Result<(), Box> { - let f = File::open("hello.txt")?; + let greeting_file = File::open("hello.txt")?; Ok(()) } diff --git a/listings/ch09-error-handling/listing-09-13/Cargo.lock b/listings/ch09-error-handling/listing-09-13/Cargo.lock new file mode 100644 index 000000000..2ae9e459e --- /dev/null +++ b/listings/ch09-error-handling/listing-09-13/Cargo.lock @@ -0,0 +1,75 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "guessing_game" +version = "0.1.0" +dependencies = [ + "rand", +] + +[[package]] +name = "libc" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/listings/ch09-error-handling/listing-09-13/Cargo.toml b/listings/ch09-error-handling/listing-09-13/Cargo.toml new file mode 100644 index 000000000..d508e9578 --- /dev/null +++ b/listings/ch09-error-handling/listing-09-13/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "guessing_game" +version = "0.1.0" +edition = "2021" + +[dependencies] +rand = "0.8.5" diff --git a/listings/ch09-error-handling/listing-09-13/src/main.rs b/listings/ch09-error-handling/listing-09-13/src/main.rs new file mode 100644 index 000000000..ad832a423 --- /dev/null +++ b/listings/ch09-error-handling/listing-09-13/src/main.rs @@ -0,0 +1,56 @@ +use rand::Rng; +use std::cmp::Ordering; +use std::io; + +// ANCHOR: here +pub struct Guess { + value: i32, +} + +impl Guess { + pub fn new(value: i32) -> Guess { + if value < 1 || value > 100 { + // "予想の値は1から100の範囲でなければなりませんが、{}でした。" + panic!("Guess value must be between 1 and 100, got {}.", value); + } + + Guess { value } + } + + pub fn value(&self) -> i32 { + self.value + } +} +// ANCHOR_END: here + +fn main() { + println!("Guess the number!"); + + let secret_number = rand::thread_rng().gen_range(1..=100); + + loop { + println!("Please input your guess."); + + let mut guess = String::new(); + + io::stdin() + .read_line(&mut guess) + .expect("Failed to read line"); + + let guess: i32 = match guess.trim().parse() { + Ok(num) => num, + Err(_) => continue, + }; + + let guess = Guess::new(guess); + + match guess.value().cmp(&secret_number) { + Ordering::Less => println!("Too small!"), + Ordering::Greater => println!("Too big!"), + Ordering::Equal => { + println!("You win!"); + break; + } + } + } +} diff --git a/listings/ch09-error-handling/no-listing-01-panic/Cargo.toml b/listings/ch09-error-handling/no-listing-01-panic/Cargo.toml index 310342cd3..660e2c819 100644 --- a/listings/ch09-error-handling/no-listing-01-panic/Cargo.toml +++ b/listings/ch09-error-handling/no-listing-01-panic/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "panic" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/no-listing-01-panic/output.txt b/listings/ch09-error-handling/no-listing-01-panic/output.txt index 1bc3dc729..c197671a6 100644 --- a/listings/ch09-error-handling/no-listing-01-panic/output.txt +++ b/listings/ch09-error-handling/no-listing-01-panic/output.txt @@ -2,5 +2,8 @@ $ cargo run Compiling panic v0.1.0 (file:///projects/panic) Finished dev [unoptimized + debuginfo] target(s) in 0.25s Running `target/debug/panic` -thread 'main' panicked at 'crash and burn', src/main.rs:2:5 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. +thread 'main' panicked at src/main.rs:2:5: +crash and burn +('main'スレッドはsrc/main.rs:2:5でパニックしました: +クラッシュして炎上) +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/listings/ch09-error-handling/no-listing-01-panic/src/main.rs b/listings/ch09-error-handling/no-listing-01-panic/src/main.rs index 32a4c243d..3e482809d 100644 --- a/listings/ch09-error-handling/no-listing-01-panic/src/main.rs +++ b/listings/ch09-error-handling/no-listing-01-panic/src/main.rs @@ -1,3 +1,4 @@ fn main() { + // "クラッシュして炎上" panic!("crash and burn"); } diff --git a/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.toml b/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.toml deleted file mode 100644 index 2a48daefb..000000000 --- a/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "error-handling" -version = "0.1.0" -authors = ["Your Name "] -edition = "2018" - -[dependencies] diff --git a/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/output.txt b/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/output.txt deleted file mode 100644 index 18262cbc4..000000000 --- a/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/output.txt +++ /dev/null @@ -1,19 +0,0 @@ -$ cargo run - Compiling error-handling v0.1.0 (file:///projects/error-handling) -error[E0308]: mismatched types - --> src/main.rs:4:18 - | -4 | let f: u32 = File::open("hello.txt"); - | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found enum `std::result::Result` - | | - | expected due to this - | - = note: expected type `u32` - found enum `std::result::Result` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. -error: could not compile `error-handling`. - -To learn more, run the command again with --verbose. diff --git a/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/src/main.rs b/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/src/main.rs deleted file mode 100644 index a637f5f95..000000000 --- a/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/src/main.rs +++ /dev/null @@ -1,7 +0,0 @@ -use std::fs::File; - -fn main() { - // ANCHOR: here - let f: u32 = File::open("hello.txt"); - // ANCHOR_END: here -} diff --git a/listings/ch09-error-handling/no-listing-03-closures/Cargo.toml b/listings/ch09-error-handling/no-listing-03-closures/Cargo.toml deleted file mode 100644 index 2a48daefb..000000000 --- a/listings/ch09-error-handling/no-listing-03-closures/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "error-handling" -version = "0.1.0" -authors = ["Your Name "] -edition = "2018" - -[dependencies] diff --git a/listings/ch09-error-handling/no-listing-03-closures/src/main.rs b/listings/ch09-error-handling/no-listing-03-closures/src/main.rs deleted file mode 100644 index c6682cd23..000000000 --- a/listings/ch09-error-handling/no-listing-03-closures/src/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::fs::File; -use std::io::ErrorKind; - -fn main() { - let f = File::open("hello.txt").unwrap_or_else(|error| { - if error.kind() == ErrorKind::NotFound { - File::create("hello.txt").unwrap_or_else(|error| { - panic!("Problem creating the file: {:?}", error); - }) - } else { - panic!("Problem opening the file: {:?}", error); - } - }); -} diff --git a/listings/ch09-error-handling/no-listing-04-unwrap/Cargo.toml b/listings/ch09-error-handling/no-listing-04-unwrap/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/no-listing-04-unwrap/Cargo.toml +++ b/listings/ch09-error-handling/no-listing-04-unwrap/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs b/listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs index 7b6b13ae7..92e9452f1 100644 --- a/listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs +++ b/listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs @@ -1,5 +1,5 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt").unwrap(); + let greeting_file = File::open("hello.txt").unwrap(); } diff --git a/listings/ch09-error-handling/no-listing-05-expect/Cargo.toml b/listings/ch09-error-handling/no-listing-05-expect/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/no-listing-05-expect/Cargo.toml +++ b/listings/ch09-error-handling/no-listing-05-expect/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/no-listing-05-expect/src/main.rs b/listings/ch09-error-handling/no-listing-05-expect/src/main.rs index cab643bc5..3759f1fa7 100644 --- a/listings/ch09-error-handling/no-listing-05-expect/src/main.rs +++ b/listings/ch09-error-handling/no-listing-05-expect/src/main.rs @@ -1,5 +1,7 @@ use std::fs::File; fn main() { - let f = File::open("hello.txt").expect("Failed to open hello.txt"); + let greeting_file = File::open("hello.txt") + // "hello.txtがこのプロジェクトに含まれているべきです" + .expect("hello.txt should be included in this project"); } diff --git a/listings/ch09-error-handling/no-listing-06-question-mark-in-main/output.txt b/listings/ch09-error-handling/no-listing-06-question-mark-in-main/output.txt deleted file mode 100644 index 17a8b2e47..000000000 --- a/listings/ch09-error-handling/no-listing-06-question-mark-in-main/output.txt +++ /dev/null @@ -1,20 +0,0 @@ -$ cargo run - Compiling error-handling v0.1.0 (file:///projects/error-handling) -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) - --> src/main.rs:4:13 - | -3 | / fn main() { -4 | | let f = File::open("hello.txt")?; - | | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()` -5 | | } - | |_- this function should return `Result` or `Option` to accept `?` - | - = help: the trait `std::ops::Try` is not implemented for `()` - = note: required by `std::ops::Try::from_error` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. -error: could not compile `error-handling`. - -To learn more, run the command again with --verbose. diff --git a/listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs b/listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs deleted file mode 100644 index 8608dc13f..000000000 --- a/listings/ch09-error-handling/no-listing-06-question-mark-in-main/src/main.rs +++ /dev/null @@ -1,5 +0,0 @@ -use std::fs::File; - -fn main() { - let f = File::open("hello.txt")?; -} diff --git a/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/Cargo.toml b/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/Cargo.toml index 2a48daefb..c496db783 100644 --- a/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/Cargo.toml +++ b/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs b/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs index e829724c5..ae237939b 100644 --- a/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs +++ b/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs @@ -2,6 +2,9 @@ fn main() { // ANCHOR: here use std::net::IpAddr; - let home: IpAddr = "127.0.0.1".parse().unwrap(); + let home: IpAddr = "127.0.0.1" + .parse() + // "ハードコードされたIPアドレスは有効であるべきです" + .expect("Hardcoded IP address should be valid"); // ANCHOR_END: here } diff --git a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock index c346748e5..2ae9e459e 100644 --- a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock +++ b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock @@ -1,87 +1,75 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "bitflags" -version = "1.2.1" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "getrandom" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "guessing_game" version = "0.1.0" dependencies = [ - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand", ] [[package]] name = "libc" -version = "0.2.53" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.5.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "rand_core" -version = "0.3.1" +name = "rand_chacha" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", + "rand_core", ] [[package]] name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)" = "ec350a9417dfd244dc9a6c4a71e13895a4db6b92f0b106f07ebbc3f3bc580cee" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml index ad5ca696d..d508e9578 100644 --- a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml +++ b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] -rand = "0.5.5" +rand = "0.8.5" diff --git a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs index d89d719aa..fc22cbc5e 100644 --- a/listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs +++ b/listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs @@ -5,7 +5,7 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1, 101); + let secret_number = rand::thread_rng().gen_range(1..=100); // ANCHOR: here loop { diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs index d2ba23b4a..e91166d2e 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/src/main.rs @@ -2,17 +2,18 @@ fn main() { let number_list = vec![34, 50, 25, 100, 65]; - let mut largest = number_list[0]; + let mut largest = &number_list[0]; - for number in number_list { + for number in &number_list { if number > largest { largest = number; } } + // "最大値は{}です" println!("The largest number is {}", largest); // ANCHOR_END: here - assert_eq!(largest, 100); + assert_eq!(*largest, 100); // ANCHOR: here } // ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs index 9138dfcb4..8c523a8be 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/src/main.rs @@ -1,9 +1,9 @@ fn main() { let number_list = vec![34, 50, 25, 100, 65]; - let mut largest = number_list[0]; + let mut largest = &number_list[0]; - for number in number_list { + for number in &number_list { if number > largest { largest = number; } @@ -13,9 +13,9 @@ fn main() { let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; - let mut largest = number_list[0]; + let mut largest = &number_list[0]; - for number in number_list { + for number in &number_list { if number > largest { largest = number; } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs index 9d8d9bfb5..899222909 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/src/main.rs @@ -17,7 +17,7 @@ fn main() { let result = largest(&number_list); println!("The largest number is {}", result); // ANCHOR_END: here - assert_eq!(result, &100); + assert_eq!(*result, 100); // ANCHOR: here let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8]; @@ -25,7 +25,7 @@ fn main() { let result = largest(&number_list); println!("The largest number is {}", result); // ANCHOR_END: here - assert_eq!(result, &6000); + assert_eq!(*result, 6000); // ANCHOR: here } // ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs index 3e2f98aab..a47e3f232 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/src/main.rs @@ -29,7 +29,7 @@ fn main() { let result = largest_i32(&number_list); println!("The largest number is {}", result); // ANCHOR_END: here - assert_eq!(result, &100); + assert_eq!(*result, 100); // ANCHOR: here let char_list = vec!['y', 'm', 'a', 'q']; @@ -37,7 +37,7 @@ fn main() { let result = largest_char(&char_list); println!("The largest char is {}", result); // ANCHOR_END: here - assert_eq!(result, &'y'); + assert_eq!(*result, 'y'); // ANCHOR: here } // ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt index 65498128d..8f209cfbe 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt @@ -1,18 +1,19 @@ $ cargo run Compiling chapter10 v0.1.0 (file:///projects/chapter10) -error[E0369]: binary operation `>` cannot be applied to type `T` +error[E0369]: binary operation `>` cannot be applied to type `&T` +(エラー: 2項演算`>`は、型`&T`に適用できません) --> src/main.rs:5:17 | 5 | if item > largest { - | ---- ^ ------- T + | ---- ^ ------- &T | | - | T + | &T | - = note: `T` might need a bound for `std::cmp::PartialOrd` - -error: aborting due to previous error +help: consider restricting type parameter `T` +(ヘルプ: 型引数`T`を制約することを考慮してください) + | +1 | fn largest(list: &[T]) -> &T { + | ++++++++++++++++++++++ For more information about this error, try `rustc --explain E0369`. -error: could not compile `chapter10`. - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` (bin "chapter10") due to 1 previous error diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs index 814fddc50..df33743f7 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/src/main.rs @@ -1,5 +1,5 @@ fn largest(list: &[T]) -> &T { - let mut largest = list[0]; + let mut largest = &list[0]; for item in list { if item > largest { diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt index 4a67e1b59..72ec7e339 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt @@ -1,14 +1,11 @@ $ cargo run Compiling chapter10 v0.1.0 (file:///projects/chapter10) error[E0308]: mismatched types +(エラー: 型が合いません) --> src/main.rs:7:38 | 7 | let wont_work = Point { x: 5, y: 4.0 }; | ^^^ expected integer, found floating-point number -error: aborting due to previous error - For more information about this error, try `rustc --explain E0308`. -error: could not compile `chapter10`. - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` (bin "chapter10") due to 1 previous error diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs index 4a08d1a8d..86b028108 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/src/main.rs @@ -1,10 +1,10 @@ -struct Point { - x: T, - y: U, +struct Point { + x: X1, + y: Y1, } -impl Point { - fn mixup(self, other: Point) -> Point { +impl Point { + fn mixup(self, other: Point) -> Point { Point { x: self.x, y: other.y, diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/lib.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/lib.rs similarity index 100% rename from listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/lib.rs rename to listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/lib.rs diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/main.rs deleted file mode 100644 index 7aa6a3bd2..000000000 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/main.rs +++ /dev/null @@ -1,23 +0,0 @@ -fn largest(list: &[T]) -> T { - let mut largest = list[0]; - - for &item in list { - if item > largest { - largest = item; - } - } - - largest -} - -fn main() { - let number_list = vec![34, 50, 25, 100, 65]; - - let result = largest(&number_list); - 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); -} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/output.txt new file mode 100644 index 000000000..fd617e751 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/output.txt @@ -0,0 +1,22 @@ +$ cargo run + Compiling chapter10 v0.1.0 (file:///projects/chapter10) +error[E0597]: `x` does not live long enough +(エラー[E0597]: `x`の生存期間が短すぎます) + --> src/main.rs:6:13 + | +5 | let x = 5; + | - binding `x` declared here + | (束縛`x`はここで宣言されています) +6 | r = &x; + | ^^ borrowed value does not live long enough + | (借用された値の生存期間が短すぎます) +7 | } + | - `x` dropped here while still borrowed + | (`x`は借用されている間にここでドロップされました) +8 | +9 | println!("r: {}", r); + | - 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 diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/main.rs new file mode 100644 index 000000000..d71134ea0 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/main.rs @@ -0,0 +1,10 @@ +fn main() { + let r; + + { + let x = 5; + r = &x; + } + + println!("r: {}", r); +} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.lock index e8007a19b..6388bb2b5 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.lock @@ -1,5 +1,3 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. [[package]] name = "chapter10" version = "0.1.0" diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt deleted file mode 100644 index e95702e78..000000000 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt +++ /dev/null @@ -1,23 +0,0 @@ -$ cargo run - Compiling chapter10 v0.1.0 (file:///projects/chapter10) -error[E0597]: `x` does not live long enough -(エラー[E0597]: `x`の生存期間が短すぎます) - --> src/main.rs:7:17 - | -7 | r = &x; - | ^^ borrowed value does not live long enough - | (借用された値の生存期間が短すぎます) -8 | } - | - `x` dropped here while still borrowed - | (`x`は借用されている間にここでドロップされました) -9 | -10 | println!("r: {}", r); - | - borrow later used here - | (その後、借用はここで使われています) - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0597`. -error: could not compile `chapter10`. - -To learn more, run the command again with --verbose. diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/rustfmt-ignore b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/rustfmt-ignore similarity index 100% rename from listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/rustfmt-ignore rename to listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/rustfmt-ignore diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs index 16adb6a0d..e8ca92328 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs @@ -1,14 +1,10 @@ fn main() { - // ANCHOR: here - { - let r; - - { - let x = 5; - r = &x; - } - - println!("r: {}", r); - } - // ANCHOR_END: here -} + let r; // ---------+-- 'a + // | + { // | + let x = 5; // -+-- 'b | + r = &x; // | | + } // -+ | + // | + println!("r: {}", r); // | +} // ---------+ diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs index 65dbf375a..09ae3919c 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs @@ -1,14 +1,8 @@ fn main() { - // ANCHOR: here - { - let r; // ---------+-- 'a - // | - { // | - let x = 5; // -+-- 'b | - r = &x; // | | - } // -+ | - // | - println!("r: {}", r); // | - } // ---------+ - // ANCHOR_END: here -} + let x = 5; // ----------+-- 'b + // | + let r = &x; // --+-- 'a | + // | | + println!("r: {}", r); // | | + // --+ | +} // ----------+ diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.lock index 6388bb2b5..e8007a19b 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "chapter10" version = "0.1.0" diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs index 94e70f00f..e1a830aad 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs @@ -1,12 +1,8 @@ fn main() { - // ANCHOR: here - { - let x = 5; // ----------+-- 'b - // | - let r = &x; // --+-- 'a | - // | | - println!("r: {}", r); // | | - // --+ | - } // ----------+ - // ANCHOR_END: here + let string1 = String::from("abcd"); + let string2 = "xyz"; + + let result = longest(string1.as_str(), string2); + // 最長の文字列は、{}です + println!("The longest string is {}", result); } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/output.txt new file mode 100644 index 000000000..ae5d43494 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/output.txt @@ -0,0 +1,20 @@ +$ cargo run + Compiling chapter10 v0.1.0 (file:///projects/chapter10) +error[E0106]: missing lifetime specifier +(エラー[E0106]: ライフタイム指定子が不足しています) + --> src/main.rs:9:33 + | +9 | fn longest(x: &str, y: &str) -> &str { + | ---- ---- ^ expected named lifetime parameter + | (名前付きライフタイム引数があるべきです) + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` + (ヘルプ: この関数の戻り値型は借用された値を含んでいますが、シグネチャは、それが`x`と`y`どちらから借用されたものなのか宣言していません) +help: consider introducing a named lifetime parameter +(ヘルプ: 名前付きライフライム引数の導入を検討してください) + | +9 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { + | ++++ ++ ++ ++ + +For more information about this error, try `rustc --explain E0106`. +error: could not compile `chapter10` (bin "chapter10") due to 1 previous error diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs index e1a830aad..6af8c9f0d 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/src/main.rs @@ -3,6 +3,15 @@ fn main() { let string2 = "xyz"; let result = longest(string1.as_str(), string2); - // 最長の文字列は、{}です println!("The longest string is {}", result); } + +// ANCHOR: here +fn longest(x: &str, y: &str) -> &str { + if x.len() > y.len() { + x + } else { + y + } +} +// ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt deleted file mode 100644 index baaf69902..000000000 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt +++ /dev/null @@ -1,20 +0,0 @@ -$ cargo run - Compiling chapter10 v0.1.0 (file:///projects/chapter10) -error[E0106]: missing lifetime specifier -(エラー[E0106]: ライフタイム指定子が不足しています) - --> src/main.rs:9:33 - | -9 | fn longest(x: &str, y: &str) -> &str { - | ^ expected lifetime parameter - | (ライフタイム引数があるべきです) - | - = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` - (助言: この関数の戻り値型は借用された値を含んでいますが、 - シグニチャは、それが`x`と`y`どちらから借用されたものなのか宣言していません) - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0106`. -error: could not compile `chapter10`. - -To learn more, run the command again with --verbose. diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs index 6af8c9f0d..09c3a0daa 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/src/main.rs @@ -7,7 +7,7 @@ fn main() { } // ANCHOR: here -fn longest(x: &str, y: &str) -> &str { +fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs index 09c3a0daa..e54d5de45 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/src/main.rs @@ -1,12 +1,18 @@ +// ANCHOR: here fn main() { - let string1 = String::from("abcd"); - let string2 = "xyz"; + // 長い文字列は長い + let string1 = String::from("long string is long"); + // (訳注:この言葉自体に深い意味はない。下の"xyz"より長いということだけが重要) - let result = longest(string1.as_str(), string2); - println!("The longest string is {}", result); + { + let string2 = String::from("xyz"); + let result = longest(string1.as_str(), string2.as_str()); + // 一番長い文字列は{} + println!("The longest string is {}", result); + } } +// ANCHOR_END: here -// ANCHOR: here fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x @@ -14,4 +20,3 @@ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { y } } -// ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/output.txt similarity index 75% rename from listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt rename to listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/output.txt index bcedda0f4..471347c68 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/output.txt @@ -3,6 +3,8 @@ $ cargo run error[E0597]: `string2` does not live long enough --> src/main.rs:6:44 | +5 | let string2 = String::from("xyz"); + | ------- binding `string2` declared here 6 | result = longest(string1.as_str(), string2.as_str()); | ^^^^^^^ borrowed value does not live long enough 7 | } @@ -10,9 +12,5 @@ error[E0597]: `string2` does not live long enough 8 | println!("The longest string is {}", result); | ------ borrow later used here -error: aborting due to previous error - For more information about this error, try `rustc --explain E0597`. -error: could not compile `chapter10`. - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` (bin "chapter10") due to 1 previous error diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs index e54d5de45..2a6fa5898 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/src/main.rs @@ -1,15 +1,12 @@ // ANCHOR: here fn main() { - // 長い文字列は長い let string1 = String::from("long string is long"); - // (訳注:この言葉自体に深い意味はない。下の"xyz"より長いということだけが重要) - + let result; { let string2 = String::from("xyz"); - let result = longest(string1.as_str(), string2.as_str()); - // 一番長い文字列は{} - println!("The longest string is {}", result); + result = longest(string1.as_str(), string2.as_str()); } + println!("The longest string is {}", result); } // ANCHOR_END: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs index 2a6fa5898..2937b194c 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/src/main.rs @@ -1,19 +1,11 @@ -// ANCHOR: here -fn main() { - let string1 = String::from("long string is long"); - let result; - { - let string2 = String::from("xyz"); - result = longest(string1.as_str(), string2.as_str()); - } - println!("The longest string is {}", result); +struct ImportantExcerpt<'a> { + part: &'a str, } -// ANCHOR_END: here -fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { - if x.len() > y.len() { - x - } else { - y - } +fn main() { + let novel = String::from("Call me Ishmael. Some years ago..."); + let first_sentence = novel.split('.').next().expect("Could not find a '.'"); + let i = ImportantExcerpt { + part: first_sentence, + }; } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.lock index e8007a19b..2aa4918e5 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "chapter10" +name = "ownership" version = "0.1.0" diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml index 6d5a0ff1d..e8847526d 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs index 25598d3f6..431a261d2 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/src/main.rs @@ -1,13 +1,29 @@ -struct ImportantExcerpt<'a> { - part: &'a str, +// ANCHOR: here +fn first_word(s: &str) -> &str { + let bytes = s.as_bytes(); + + for (i, &item) in bytes.iter().enumerate() { + if item == b' ' { + return &s[0..i]; + } + } + + &s[..] } +// ANCHOR_END: here fn main() { - // 僕をイシュマエルとお呼び。何年か前・・・ - let novel = String::from("Call me Ishmael. Some years ago..."); - // "'.'が見つかりませんでした" - let first_sentence = novel.split('.').next().expect("Could not find a '.'"); - let i = ImportantExcerpt { - part: first_sentence, - }; + let my_string = String::from("hello world"); + + // first_word works on slices of `String`s + let word = first_word(&my_string[..]); + + let my_string_literal = "hello world"; + + // first_word works on slices of string literals + let word = first_word(&my_string_literal[..]); + + // Because string literals *are* string slices already, + // this works too, without the slice syntax! + let word = first_word(my_string_literal); } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.toml deleted file mode 100644 index 686de938f..000000000 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "ownership" -version = "0.1.0" -authors = ["Your Name "] -edition = "2018" - -[dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/src/main.rs deleted file mode 100644 index 431a261d2..000000000 --- a/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/src/main.rs +++ /dev/null @@ -1,29 +0,0 @@ -// ANCHOR: here -fn first_word(s: &str) -> &str { - let bytes = s.as_bytes(); - - for (i, &item) in bytes.iter().enumerate() { - if item == b' ' { - return &s[0..i]; - } - } - - &s[..] -} -// ANCHOR_END: here - -fn main() { - let my_string = String::from("hello world"); - - // first_word works on slices of `String`s - let word = first_word(&my_string[..]); - - let my_string_literal = "hello world"; - - // first_word works on slices of string literals - let word = first_word(&my_string_literal[..]); - - // Because string literals *are* string slices already, - // this works too, without the slice syntax! - let word = first_word(my_string_literal); -} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs index 47de4d5c0..f4f66890e 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs @@ -1,7 +1,6 @@ -use chapter10::{self, Summary, Tweet}; +use aggregator::{Summary, Tweet}; fn main() { - // ANCHOR: here let tweet = Tweet { username: String::from("horse_ebooks"), content: String::from( @@ -13,5 +12,4 @@ fn main() { }; println!("1 new tweet: {}", tweet.summarize()); - // ANCHOR_END: here } diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs index f659ea6ad..56f49bb8b 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/src/main.rs @@ -1,4 +1,4 @@ -use chapter10::{self, NewsArticle, Summary}; +use aggregator::{self, NewsArticle, Summary}; fn main() { // ANCHOR: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs index 466dc4d59..e05e8e1c6 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/src/main.rs @@ -1,4 +1,4 @@ -use chapter10::{self, Summary, Tweet}; +use aggregator::{self, Summary, Tweet}; fn main() { // ANCHOR: here diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.lock b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.lock index e8007a19b..2835471f0 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.lock +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "chapter10" +name = "aggregator" version = "0.1.0" - diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml index 6d5a0ff1d..46f46a7f4 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "chapter10" +name = "aggregator" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.toml deleted file mode 100644 index 6d5a0ff1d..000000000 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "chapter10" -version = "0.1.0" -authors = ["Your Name "] -edition = "2018" - -[dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt deleted file mode 100644 index a225d01f3..000000000 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt +++ /dev/null @@ -1,37 +0,0 @@ -$ cargo run - Compiling chapter10 v0.1.0 (file:///projects/chapter10) -error[E0508]: cannot move out of type `[T]`, a non-copy slice -(エラー[E0508]: 型`[T]`をもつ、非コピーのスライスからのムーブはできません) - --> src/main.rs:2:23 - | -2 | let mut largest = list[0]; - | ^^^^^^^ - | | - | cannot move out of here - | (ここからムーブすることはできません) - | move occurs because `list[_]` has type `T`, which does not implement the `Copy` trait - | (ムーブが発生するのは、`list[_]`は`T`という、`Copy`トレイトを実装しない型であるためです) - | help: consider borrowing here: `&list[0]` - | (助言:借用するようにしてみてはいかがですか: `&list[0]`) - -error[E0507]: cannot move out of a shared reference -(エラー[E0507]:共有の参照からムーブはできません) - --> src/main.rs:4:18 - | -4 | for &item in list { - | ----- ^^^^ - | || - | |data moved here - | |(データがここでムーブされています) - | |move occurs because `item` has type `T`, which does not implement the `Copy` trait - | |(ムーブが発生するのは、`item`は`T`という、`Copy`トレイトを実装しない型であるためです) - | help: consider removing the `&`: `item` - | (助言:`&`を取り除いてみてはいかがですか: `item`) - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0507, E0508. -For more information about an error, try `rustc --explain E0507`. -error: could not compile `chapter10`. - -To learn more, run the command again with --verbose. diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/src/main.rs b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/src/main.rs deleted file mode 100644 index 525ce815a..000000000 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/src/main.rs +++ /dev/null @@ -1,25 +0,0 @@ -// ANCHOR: here -fn largest(list: &[T]) -> T { - // ANCHOR_END: here - let mut largest = list[0]; - - for &item in list { - if item > largest { - largest = item; - } - } - - largest -} - -fn main() { - let number_list = vec![34, 50, 25, 100, 65]; - - let result = largest(&number_list); - 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); -} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/Cargo.toml new file mode 100644 index 000000000..4dbde9090 --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "chapter10" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/src/lib.rs b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/src/lib.rs new file mode 100644 index 000000000..05b07c31a --- /dev/null +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/src/lib.rs @@ -0,0 +1,9 @@ +// ANCHOR: here +fn some_function(t: &T, u: &U) -> i32 +where + T: Display + Clone, + U: Clone + Debug, +{ + // ANCHOR_END: here + unimplemented!() +} diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt index acdf96e4e..05420c7d7 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt @@ -1,20 +1,16 @@ $ cargo run Compiling chapter10 v0.1.0 (file:///projects/chapter10) error[E0515]: cannot return value referencing local variable `result` -(エラー[E0515]: ローカル変数`result`を参照している値は返せません) +(エラー[E0515]: ローカル変数`result`を参照する値を返すことはできません) --> src/main.rs:11:5 | 11 | result.as_str() | ------^^^^^^^^^ | | | returns a value referencing data owned by the current function + | (現在の関数に所有されているデータを参照する値を返しています) | `result` is borrowed here - | (現在の関数に所有されているデータを参照する値を返しています - | `result`はここで借用されています) - -error: aborting due to previous error + | (`result`はここで借用されています) For more information about this error, try `rustc --explain E0515`. -error: could not compile `chapter10`. - -To learn more, run the command again with --verbose. +error: could not compile `chapter10` (bin "chapter10") due to 1 previous error diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/Cargo.toml b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/Cargo.toml index 6d5a0ff1d..489f80967 100644 --- a/listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/Cargo.toml +++ b/listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 26386ca98..24d253292 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -73,12 +73,12 @@ - [Enumとパターンマッチング](ch06-00-enums.md) - [Enumを定義する](ch06-01-defining-an-enum.md) - - [`match`制御フロー演算子](ch06-02-match.md) + - [`match`制御フロー構造](ch06-02-match.md) - [`if let`で簡潔な制御フロー](ch06-03-if-let.md) - [エラー処理](ch09-00-error-handling.md) - [`panic!`で回復不能なエラー](ch09-01-unrecoverable-errors-with-panic.md) diff --git a/src/ch00-00-introduction.md b/src/ch00-00-introduction.md index 327055d08..f690afb48 100644 --- a/src/ch00-00-introduction.md +++ b/src/ch00-00-introduction.md @@ -13,7 +13,7 @@ > 注釈: この本のこの版は、本として利用可能な[The Rust Programming Language][nsprust]と、 > [No Starch Press][nsp]のebook形式と同じです。 -[nsprust]: https://nostarch.com/rust +[nsprust]: https://nostarch.com/rust-programming-language-2nd-edition [nsp]: https://nostarch.com/ * Cargoは、付属の依存関係管理ツール兼ビルドツールで、依存関係の追加、コンパイル、管理を容易にし、Rustのエコシステム全体で一貫性を持たせます。 -* Rustfmtは開発者の間で一貫したコーディングスタイルを保証します。 +* Rustfmtフォーマットツールは開発者の間で一貫したコーディングスタイルを保証します。 * Rust言語サーバーは、IDE(統合開発環境)との統合により、コード補完やインラインエラーメッセージに対応しています。 @@ -161,17 +162,17 @@ Rustは、Rustプログラミング言語やコミュニティ、開発者ツー Rustは、スピードと安定性を言語に渇望する方向けです。ここでいうスピードとは、 -Rustで作れるプログラムのスピードとソースコードを書くスピードのことです。Rustコンパイラのチェックにより、 +Rustコードの実行速度とプログラムを書くスピードのことです。Rustコンパイラのチェックにより、 機能の追加とリファクタリングを通して安定性を保証してくれます。これはこのようなチェックがない言語の脆いレガシーコードとは対照的で、 その場合開発者はしばしば、変更するのを恐れてしまいます。ゼロコスト抽象化を志向し、 手で書いたコードと同等の速度を誇る低レベルコードにコンパイルされる高レベル機能により、 @@ -218,12 +219,12 @@ reading a book that specifically provides an introduction to programming. 一般的に、この本は、順番に読み進めていくことを前提にしています。後の章は、前の章の概念の上に成り立ち、 -前の章では、ある話題にさほど深入りしない可能性があります; 典型的に後ほどの章で同じ話題を再度しています。 +前の章では、特定の話題にさほど深入りしない可能性がありますが、後ほどの章で同じ話題を再検討するでしょう。 第1章はRustのインストール方法、“Hello, world!”プログラムの書き方、Rustのパッケージマネージャ兼、 -ビルドツールのCargoの使用方法を説明します。第2章は、Rust言語への実践的な導入です。ここでは概念をざっくりと講義し、後ほどの章で追加の詳細を提供します。 -今すぐRustの世界に飛び込みたいなら、第2章こそがそのためのものです。第3章は他のプログラミング言語の機能に似たRustの機能を講義していますが、 -最初その3章すら飛ばして、まっすぐに第4章に向かい、Rustの所有権システムについて学びたくなる可能性があります。 -しかしながら、あなたが次に進む前に全ての詳細を学ぶことを好む特別に几帳面な学習者なら、 +ビルドツールのCargoの使用方法を説明します。第2章は、数当てゲームを作りながら、実際にRustでのプログラミングをやってもらう導入です。 +ここでは概念をざっくりと講義し、後ほどの章で追加の詳細を提供します。 +今すぐRustの世界に飛び込みたいなら、第2章こそがそのためのものです。第3章は他のプログラミング言語の機能に似たRustの機能を講義し、 +第4章ではRustの所有権システムについて学びます。 +あなたが次に進む前に全ての詳細を学ぶことを好む特別に几帳面な学習者なら、 第2章を飛ばして真っ先に第3章に行き、学んだ詳細を適用するプロジェクトに取り組みたくなった時に第2章に戻りたくなる可能性があります。 最後に、言語についての有用な情報をよりリファレンスのような形式で含む付録があります。 付録AはRustのキーワードを講義し、付録Bは、Rustの演算子と記号、付録Cは、 標準ライブラリが提供する導出可能なトレイト、付録Dはいくつか便利な開発ツールを講義し、 -付録EではRustのエディションについて説明します。 - +付録EではRustのエディションについて説明します。付録Fではこの本の翻訳を見つけることができ、 +付録GではRustの作られ方、そしてnightly Rustとは何かについて講義します。 -| Ferris | Meaning | -|------------------------------------------------------------------------|--------------------------------------------------| -| | このコードはコンパイルできません! | -| | このコードはパニックします! | -| | このコードはアンセーフなコードを含みます。 | -| | このコードは求められている振る舞いをしません。 | +| Ferris | Meaning | +|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| +| Ferris with a question mark | このコードはコンパイルできません! | +| Ferris throwing up their hands | このコードはパニックします! | +| Ferris with one claw up, shrugging | このコードは求められている振る舞いをしません。 | -> 注釈: なんらかの理由で`rustup`を使用したくない場合、[Rustインストールページ][rust-installation-page]で、 +> 注釈: なんらかの理由で`rustup`を使用したくない場合、[Other Rust Installation Methods ページ][otherinstall]で、 > 他の選択肢をご覧になってください。 -> 訳注:日本語版のRustインストールページは[こちら][rust-installation-page-ja]です。 - -[rust-installation-page]: https://www.rust-lang.org/tools/install/ -[rust-installation-page-ja]: https://www.rust-lang.org/ja/tools/install/ - 以下の手順で最新の安定版のRustコンパイラをインストールします。 @@ -45,16 +40,17 @@ Rustは安定性 (stability) を保証しているので、現在この本の例 > > In this chapter and throughout the book, we’ll show some commands used in the > terminal. Lines that you should enter in a terminal all start with `$`. You -> don’t need to type in the `$` character; it indicates the start of each -> command. Lines that don’t start with `$` typically show the output of the -> previous command. Additionally, PowerShell-specific examples will use `>` -> rather than `$`. +> don’t need to type the `$` character; it’s the command line prompt shown to +> indicate the start of each command. Lines that don’t start with `$` typically +> show the output of the previous command. Additionally, PowerShell-specific +> examples will use `>` rather than `$`. --> > ### コマンドラインの記法 > > この章及び、本を通して、端末で使用するなんらかのコマンドを示すことがあります。読者が入力するべき行は、 -> 全て`$`で始まります。ただし、読者が`$`文字を入力する必要はありません; これは各コマンドの開始を示しているだけです。 +> 全て`$`で始まります。ただし、読者が`$`文字を入力する必要はありません; +> これは各コマンドの開始を示すために表示しているコマンドラインプロンプトです。 > `$`で始まらない行は、典型的には直前のコマンドの出力を示します。また、PowerShell限定の例には、 > `$`ではなく、`>`を使用します。 @@ -88,22 +84,37 @@ Rust is installed now. Great! ``` + +*リンカ*も必要になるでしょう。 +リンカは、コンパイルされた出力をひとつのファイルに合体させるためにRustが使用するプログラムです。 +リンカが既にインストールされている可能性は高いでしょう。 +リンカエラーが発生したときは、Cコンパイラは典型的にリンカを含んでいるでしょうから、Cコンパイラをインストールすべきです。 +一般的なRustパッケージの中には、Cコードに依存し、Cコンパイラが必要になるものもあるので、この理由からもCコンパイラは有用です。 + + + +macOSでは、以下を実行することでCコンパイラが手に入ります: + +```console +$ xcode-select --install +``` + + -これに加えて、なんらかのリンカが必要になるでしょう。既にインストールされている可能性は高いものの、 -Rustプログラムをコンパイルしようとした時、リンカが実行できないというエラーが出たら、 -システムにリンカがインストールされていないということなので、手動でインストールする必要があるでしょう。 -Cコンパイラは通常正しいリンカとセットになっています。 -自分のプラットフォームのドキュメンテーションを見てCコンパイラのインストール方法を確認してください。 -一般的なRustパッケージの中には、Cコードに依存し、Cコンパイラが必要になるものもあります。 -ですので、Cコンパイラは今のうちにインストールしておく価値があるかもしれません。 +Linuxユーザは、通常はディストリビューションのドキュメントに従って、GCCまたはClangをインストールするべきです。 +例えばUbuntuを使用している場合は、`build-essential`パッケージをインストールすれば大丈夫です。 Windowsでは、[https://www.rust-lang.org/tools/install][install]に行き、手順に従ってRustをインストールしてください。 -インストールの途中で、Visual Studio 2013以降用のC++ビルドツールも必要になるという旨のメッセージが出るでしょう。 -ビルドツールを取得する最も簡単な方法は、[Visual Studio 2019用のビルドツール][visualstudio]をインストールすることです。 -どのワークロード (workloads) をインストールするかと質問されたときは、"C++ build tools"が選択されており、Windows 10 SDKと英語の言語パック (English language pack) が含まれていることを確かめてください。 +インストールの途中で、Visual Studio 2013以降用のMSVCビルドツールも必要になるという旨のメッセージが出るでしょう。 -> 訳注:Windowsの言語を日本語にしている場合は言語パックのところで「日本語」が選択されており、そのままの設定でインストールしても基本的に問題ないはずです。しかし、サードパーティーのツールやライブラリの中には英語の言語パックを必要とするものがあるため、「日本語」に加えて「英語」も選択することをお勧めします。 + -[install]: https://www.rust-lang.org/tools/install -[visualstudio]: https://visualstudio.microsoft.com/visual-cpp-build-tools/ +ビルドツールを取得するには、[Visual Studio 2022][visualstudio]をインストールする必要があるでしょう。 +どのワークロード (workloads) をインストールするかと質問されたときは、以下を含めてください: + + + +* 「C++によるデスクトップ開発」(“Desktop Development with C++”) +* Windows 10または11のSDK +* 英語の言語パック (English language pack) コンポーネント (お好みで他の任意の言語パックも) + +> 訳注:Windowsの言語を日本語にしている場合は言語パックのところで「日本語」が選択されており、そのままの設定でインストールしても基本的に問題ないはずです。しかし、サードパーティーのツールやライブラリの中には英語の言語パックを必要とするものがあるため、「日本語」に加えて「英語」も選択することをお勧めします。 -### 更新及びアンインストール +### トラブルシューティング -`rustup`経由でRustをインストールしたなら、最新版へ更新するのは簡単です。 -シェルから以下の更新スクリプトを実行してください: +Rustが正常にインストールされているか確かめるには、シェルを開いて以下の行を入力してください: ```console -$ rustup update +$ rustc --version ``` -Rustと`rustup`をアンインストールするには、シェルから以下のアンインストールスクリプトを実行してください: +バージョンナンバー、コミットハッシュ、最新の安定版がリリースされたコミット日時が以下のフォーマットで表示されるのを目撃するはずです。 -```console -$ rustup self uninstall +```text +rustc x.y.z (abcabcabc yyyy-mm-dd) ``` -### トラブルシューティング +この情報が見られたなら、Rustのインストールに成功しています! +この情報が出ない場合は、次のようにしてRustが`%PATH%`システム環境変数にあることを確認してください。 -Rustが正常にインストールされているか確かめるには、シェルを開いて以下の行を入力してください: +Windows CMDでは: ```console -$ rustc --version +> echo %PATH% ``` -バージョンナンバー、コミットハッシュ、最新の安定版がリリースされたコミット日時が以下のフォーマットで表示されるのを目撃するはずです。 +PowerShellでは: -```text -rustc x.y.z (abcabcabc yyyy-mm-dd) +```powershell +> echo $env:Path ``` -この情報が見られたなら、Rustのインストールに成功しています!この情報が出ず、Windowsを使っているなら、 -Rustが`%PATH%`システム環境変数にあることを確認してください。これらが全て正常であるのに、それでもRustがうまく動かないなら、 -助力を得られる場所はたくさんあります。最も簡単なのが[Rustの公式Discord][discord]の#beginnersチャンネルです。そのアドレスで、助けてくれる他のRustacean (Rustユーザが自分たちのことを呼ぶ、冗談めいたニックネーム) たちとチャットできます。 -他にも、素晴らしいリソースとして[ユーザ・フォーラム][users]と[Stack Overflow][stackoverflow]が挙げられます。 +LinuxおよびmacOSでは: + +```console +$ echo $PATH +``` + + + +これらが全て正常であるのに、それでもRustがうまく動かないなら、助力を得られる場所はたくさんあります。 +他のRustacean(Rustユーザが自分たちのことを呼ぶ、冗談めいたニックネーム)たちと交流する方法を[コミュニティページ][community]で探してください。 > 訳注1:Rustaceanについて、いらないかもしれない補足です。[公式Twitter曰く、Rustaceanはcrustaceans(甲殻類)から来ている][twitter]そうです。 > そのため、Rustのマスコットは(非公式らしいですが)[カニ][mascott]。上の会話でCの欠点を削ぎ落としているからcを省いてるの?みたいなことを聞いていますが、 > 違うそうです。検索したら、堅牢性が高いから甲殻類という意見もありますが、真偽は不明です。 > 明日使えるかもしれないトリビアでした。 -> 訳注2:上にある公式Discordは英語話者のコミュニティです。日本語話者のためのコミュニティが[Zulip rust-lang-jpにあり][zulip_jp]、こちらでもRustaceanたちが活発に議論をしています。 +> 訳注2:上にあるコミュニティページはどれも英語話者のコミュニティへのリンク集です。日本語話者のためのコミュニティが[Zulip rust-lang-jpにあり][zulip_jp]、こちらでもRustaceanたちが活発に議論をしています。 > 公式Discord同様、初心者向けの#beginnersチャンネルが存在するので、気軽に質問してみてください。 -[discord]: https://discord.gg/rust-lang -[users]: https://users.rust-lang.org/ -[stackoverflow]: https://stackoverflow.com/questions/tagged/rust [twitter]: https://mobile.twitter.com/rustlang/status/916284650674323457 [mascott]: https://www.slideshare.net/wolf-dog/ss-64026540 [zulip_jp]: https://rust-lang-jp.zulipchat.com + + +### 更新及びアンインストール + + + +`rustup`経由でRustがインストールされたなら、新しくリリースされた版へ更新するのは簡単です。 +シェルから以下の更新スクリプトを実行してください: + +```console +$ rustup update +``` + + + +Rustと`rustup`をアンインストールするには、シェルから以下のアンインストールスクリプトを実行してください: + +```console +$ rustup self uninstall +``` + @@ -234,12 +286,12 @@ Rustが`%PATH%`システム環境変数にあることを確認してくださ ### ローカルのドキュメンテーション -インストールされたRustには、ローカルに複製されたドキュメンテーションのコピーが含まれているので、これをオフラインで閲覧することができます。 +インストールされたRustには、オフラインでドキュメンテーションを閲覧できるように、ドキュメンテーションのローカルコピーが含まれています。 ブラウザでローカルのドキュメンテーションを開くには、`rustup doc`を実行してください。 標準ライブラリにより提供される型や関数がなんなのかや、それをどう使えば良いのかがよくわからないときは、いつでもAPIのドキュメンテーションを検索してみてください! + + +[otherinstall]: https://forge.rust-lang.org/infra/other-installation-methods.html +[install]: https://www.rust-lang.org/tools/install +[visualstudio]: https://visualstudio.microsoft.com/downloads/ +[community]: https://www.rust-lang.org/community diff --git a/src/ch01-02-hello-world.md b/src/ch01-02-hello-world.md index d517eef33..686cbfdb5 100644 --- a/src/ch01-02-hello-world.md +++ b/src/ch01-02-hello-world.md @@ -5,9 +5,9 @@ ## Hello, World! Rustをインストールしたので、最初のRustプログラムを書きましょう。新しい言語を学ぶ際に、 @@ -19,16 +19,17 @@ Rustをインストールしたので、最初のRustプログラムを書きま > no specific demands about your editing or tooling or where your code lives, so > if you prefer to use an integrated development environment (IDE) instead of > the command line, feel free to use your favorite IDE. Many IDEs now have some -> degree of Rust support; check the IDE’s documentation for details. Recently, -> the Rust team has been focusing on enabling great IDE support, and progress -> has been made rapidly on that front! +> degree of Rust support; check the IDE’s documentation for details. The Rust +> team has been focusing on enabling great IDE support via `rust-analyzer`. See +> [Appendix D][devtools] for more details. --> > 注釈: この本は、コマンドラインに基礎的な馴染みがあることを前提にしています。Rustは、編集やツール、 > どこにコードがあるかについて特定の要求をしないので、コマンドラインではなくIDEを使用することを好むのなら、 > どうぞご自由にお気に入りのIDEを使用してください。今では、多くのIDEがなんらかの形でRustをサポートしています; -> 詳しくは、IDEのドキュメンテーションをご覧ください。最近、Rustチームは優れたIDEサポートを有効にすることに注力し、 -> その前線で急激に成果があがっています! +> 詳しくは、IDEのドキュメンテーションをご覧ください。 +> Rustチームは`rust-analyzer`を介して優れたIDEサポートを可能にすることに注力しています。 +> 詳しくは[付録D][devtools]をご覧ください。 端末を開いて以下のコマンドを入力し、*projects*ディレクトリと、 -*projects*ディレクトリ内にHello, world!プロジェクトのディレクトリを作成してください。 +*projects*ディレクトリ内に「Hello, world!」プロジェクトのディレクトリを作成してください。 -LinuxとmacOSなら、こう入力してください: +Linux、macOS、そしてWindows上のPowerShellなら、こう入力してください: -```text +```console $ mkdir ~/projects $ cd ~/projects $ mkdir hello_world @@ -80,19 +81,6 @@ Windowsのcmdなら、こう: > cd hello_world ``` - - -WindowsのPowerShellなら、こう: - -```powershell -> mkdir $env:USERPROFILE\projects -> cd $env:USERPROFILE\projects -> mkdir hello_world -> cd hello_world -``` - @@ -101,13 +89,13 @@ WindowsのPowerShellなら、こう: 次にソースファイルを作り、*main.rs*というファイル名にしてください。Rustのファイルは常に *.rs*という拡張子で終わります。 -ファイル名に2単語以上使っているなら、アンダースコアで区切ってください。例えば、*helloworld.rs*ではなく、 +ファイル名に2単語以上使っているなら、アンダースコアで区切るのが規約です。例えば、*helloworld.rs*ではなく、 *hello_world.rs*を使用してください。 -ファイルを保存し、端末ウィンドウに戻ってください。LinuxかmacOSなら、以下のコマンドを打ってファイルをコンパイルし、 -実行してください: +ファイルを保存し、*~/projects/hello_world*ディレクトリの端末ウィンドウに戻ってください。 +LinuxかmacOSなら、以下のコマンドを打ってファイルをコンパイルし、実行してください: -```text +```console $ rustc main.rs $ ./main Hello, world! @@ -163,16 +152,17 @@ Hello, world! OSに関わらず、`Hello, world!`という文字列が端末に出力されるはずです。この出力が見れないなら、 -「トラブルシューティング」節に立ち戻って、助けを得る方法を参照してください。 +インストールの節の[「トラブルシューティング」][troubleshooting]の部分に立ち戻って、助けを得る方法を参照してください。 `Hello, world!`が確かに出力されたら、おめでとうございます!正式にRustプログラムを書きました。 @@ -185,11 +175,11 @@ Rustプログラマになったのです!ようこそ! ### Rustプログラムの解剖 -Hello, world!プログラムでいま何が起こったのか詳しく確認しましょう。 +この「Hello, world!」プログラムを詳しく再確認しましょう。 こちらがパズルの最初のピースです: ```rust @@ -199,42 +189,41 @@ fn main() { ``` -これらの行でRustで関数を定義しています。`main`関数は特別です: 常に全ての実行可能なRustプログラムで走る最初のコードになります。 -1行目は、引数がなく、何も返さない`main`という関数を宣言しています。引数があるなら、かっこ(`()`)の内部に入ります。 +これらの行は`main`という名前の関数を定義しています。`main`関数は特別です: 常に全ての実行可能なRustプログラムで走る最初のコードになります。 +ここで、1行目は、引数がなく何も返さない`main`という関数を宣言しています。引数があるなら、かっこ(`()`)の内部に入ります。 -また、関数の本体が波括弧(`{}`)に包まれていることにも注目してください。Rustでは、全ての関数本体の周りにこれらが必要になります。 +関数の本体は`{}`に包まれます。Rustでは、全ての関数本体の周りに波括弧が必要になります。 スペースを1つあけて、開き波括弧を関数宣言と同じ行に配置するのがいいスタイルです。 -複数のRustプロジェクトに渡って標準的なスタイルにこだわりたいなら、`rustfmt`を使うことでコードを決まったスタイルに整形できるでしょう。 -Rustチームは、`rustc`のように標準的なRustの配布にこのツールを含んでいるため、既にコンピューターにインストールされているはずです! -詳細は、オンラインのドキュメンテーションを確認してください。 +> 注釈: 複数のRustプロジェクトに渡って標準的なスタイルにこだわりたいなら、`rustfmt`を使うことでコードを決まったスタイルに整形できるでしょう(`rustfmt`の詳細は[付録D][devtools]で)。 +> Rustチームは、`rustc`のように標準的なRustの配布にこのツールを含んでいるため、既にコンピューターにインストールされているはずです! -`main`関数内には、こんなコードがあります: +`main`関数の本体は、こんなコードを抱えています: ```rust println!("Hello, world!"); @@ -242,23 +231,29 @@ Inside the `main` function is the following code: この行が、この小さなプログラムの全作業をしています: テキストを画面に出力するのです。 -ここで気付くべき重要な詳細が4つあります。まず、Rustのスタイルは、タブではなく、4スペースでインデントするということです。 +ここで気付くべき重要な詳細が4つあります。 + +まず、Rustのスタイルは、タブではなく、4スペースでインデントするということです。 + + 2番目に`println!`はRustのマクロを呼び出すということです。代わりに関数を呼んでいたら、 `println`(`!`なし)と入力されているでしょう。Rustのマクロについて詳しくは、第19章で議論します。 -とりあえず、`!`を使用すると、普通の関数ではなくマクロを呼んでいるのだということを知っておくだけでいいでしょう。 +とりあえず、`!`を使用すると、普通の関数ではなくマクロを呼んでいるのだということと、マクロは関数と同じルールには必ずしも従わないということを知っておくだけでいいでしょう。 -Linux、macOS、WindowsのPowerShellなら、シェルで以下のように`ls`コマンドを入力することで実行可能ファイルを見られます: +Linux、macOS、WindowsのPowerShellなら、シェルで`ls`コマンドを入力することで実行可能ファイルを見られます: -```text +```console $ ls main main.rs ``` +LinuxとmacOSでは、2つのファイルが見えるでしょう。 +WindowsのPowerShellでは、CMDを使ったときに見ることになるのと同じ3つのファイルが見えるでしょう。 WindowsのCMDなら、以下のように入力するでしょう: ```cmd @@ -340,29 +339,25 @@ main.rs これは、*.rs*拡張子のソースコードファイル、実行可能ファイル(Windowsなら*main.exe*、他のプラットフォームでは、*main*)、 -そして、CMDを使用しているなら、*.pdb*拡張子のデバッグ情報を含むファイルを表示します。ここから、 +そして、Windowsを使用しているなら、*.pdb*拡張子のデバッグ情報を含むファイルを表示します。ここから、 *main*か*main.exe*を走らせます。このように: -```text +```console $ ./main # or .\main.exe on Windows # または、Widnowsなら.\main.exe ``` -*main.rs*がHello, world!プログラムなら、この行は`Hello, world!`と端末に出力するでしょう。 - - +*main.rs*がHello, world!プログラムなら、この行は`Hello, world!`と端末に出力します。 + +[troubleshooting]: ch01-01-installation.html#トラブルシューティング +[devtools]: appendix-04-useful-development-tools.html diff --git a/src/ch01-03-hello-cargo.md b/src/ch01-03-hello-cargo.md index 8b4284a65..6a9fe8884 100644 --- a/src/ch01-03-hello-cargo.md +++ b/src/ch01-03-hello-cargo.md @@ -19,14 +19,14 @@ CargoはRustのビルドシステム兼パッケージマネージャです。 いままでに書いたようなごく単純なRustプログラムには依存がありません。 -そのため「Hello, world!」プロジェクトをCargoでビルドしても、Cargoの中のコードをビルドする部分しか使わないでしょう。 +「Hello, world!」プロジェクトをCargoでビルドしても、Cargoの中のコードをビルドする部分しか使わないでしょう。 より複雑なRustプログラムを書くようになると依存を追加することになりますが、Cargoを使ってプロジェクトを開始したなら、依存の追加もずっと簡単になります。 Rustプロジェクトの大多数がCargoを使用しているので、これ以降、この本では、あなたもCargoを使用していると想定します。 @@ -63,9 +63,9 @@ determine how to install Cargo separately. Cargoを使って新しいプロジェクトを作成し、元の「Hello, world!」プロジェクトとの違いを見ていきましょう。 @@ -78,12 +78,12 @@ $ cd hello_cargo ``` -最初のコマンドは*hello_cargo*という名の新しいディレクトリを作成します。 +最初のコマンドは*hello_cargo*という名の新しいディレクトリとプロジェクトを作成します。 プロジェクトを*hello_cargo*と名付けたので、Cargoはそれに関連するいくつかのファイルを同名のディレクトリに作成します。 -このファイルは[TOML](https://toml.io)(*Tom's Obvious, Minimal Language*、トムの明確な最小限の言語)形式で、Cargoの設定フォーマットです。 +このファイルは[*TOML*][toml](*Tom's Obvious, Minimal Language*、トムの明確な最小限の言語)形式で、Cargoの設定フォーマットです。 Cargoはリスト1-1で書いたような「Hello, world!」プログラムを生成してくれています。 -これまでのところ、以前のプロジェクトとCargoが生成したプロジェクトの違いは、Cargoがコードを*src*ディレクトリに配置したことと、 +これまでのところ、私たちのプロジェクトとCargoが生成したプロジェクトの違いは、Cargoがコードを*src*ディレクトリに配置したことと、 最上位のディレクトリに*Cargo.toml*設定ファイルがあることです。 このコマンドは実行ファイルを現在のディレクトリではなく、*target/debug/hello_cargo*(Windowsでは*target/debug/hello_cargo.exe*)に作成します。 +デフォルトのビルドはデバッグビルドなので、Cargoはバイナリを*debug*という名前のディレクトリの中に入れます。 以下のコマンドで実行ファイルを実行できます。 ```console $ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows -$ # Windowsでは .\target\debug\hello_cargo.exe + # Windowsでは .\target\debug\hello_cargo.exe Hello, world! ``` @@ -290,7 +294,7 @@ Cargoがその内容を管理してくれます。 先ほどは`cargo build`でプロジェクトをビルドし、`./target/debug/hello_cargo`で実行しました。 @@ -303,15 +307,25 @@ $ cargo run Hello, world! ``` + + +`cargo run`を使ったほうが、`cargo build`を忘れずに実行した後バイナリへのパス全体を使わないといけないのと比較して便利なので、 +ほとんどの開発者は`cargo run`を使います。 + 今回はCargoが`hello_cargo`をコンパイルしていることを示す出力がないことに注目してください。 -Cargoはファイルが変更されていないことに気づいたので、単にバイナリを実行したのです。 +Cargoはファイルが変更されていないことに気づいたので、再ビルドせずに単にバイナリを実行したのです。 もしソースコードを変更していたら、Cargoは実行前にプロジェクトを再ビルドし、以下のような出力が表示されたことでしょう。 ```console @@ -338,16 +352,17 @@ $ cargo check なぜ実行可能ファイルが欲しくないのでしょうか? `cargo check`は実行ファイルを生成するステップを省くことができるので、多くの場合、`cargo build`よりもずっと高速です。 -もし、あなたがコードを書きながら継続的にチェックするのなら、`cargo check`を使えば、そのプロセスを高速化できます! +もし、あなたがコードを書きながら継続的にチェックするのなら、`cargo check`を使えば、プロジェクトのコンパイルがまだ通るか教えてくれるプロセスを高速化できます! そのため多くのRustaceanはプログラムを書きながら定期的に`cargo check`を実行し、コンパイルできるか確かめます。 そして、実行ファイルを使う準備ができたときに`cargo build`を走らせるのです。 @@ -418,13 +433,14 @@ the executable in *target/release*. 単純なプロジェクトでは、Cargoは単に`rustc`を使うことに対してあまり多くの価値を生みません。 しかし、プログラムが複雑になるにつれて、その価値を証明することになるでしょう。 -複数のクレートからなる複雑なプロジェクトでは、Cargoにビルドを調整させるほうがずっと簡単です。 +プログラムが複数のファイルに分かれるほど大きくなったり、依存が必要になってくると、 +Cargoにビルドを調整させるほうがずっと簡単です。 -Cargoの詳細については、[ドキュメント]を参照してください。 - -[ドキュメント]: https://doc.rust-lang.org/cargo/ +Cargoの詳細については、[ドキュメント][cargo]を参照してください。 [installation]: ch01-01-installation.html#インストール +[toml]: https://toml.io [appendix-e]: appendix-05-editions.html +[cargo]: https://doc.rust-lang.org/cargo/ diff --git a/src/ch02-00-guessing-game-tutorial.md b/src/ch02-00-guessing-game-tutorial.md index b90da438d..ed1a080f9 100644 --- a/src/ch02-00-guessing-game-tutorial.md +++ b/src/ch02-00-guessing-game-tutorial.md @@ -8,15 +8,15 @@ Let’s jump into Rust by working through a hands-on project together! This chapter introduces you to a few common Rust concepts by showing you how to use them in a real program. You’ll learn about `let`, `match`, methods, associated -functions, using external crates, and more! In the following chapters, we’ll -explore these ideas in more detail. In this chapter, you’ll practice the +functions, external crates, and more! In the following chapters, we’ll explore +these ideas in more detail. In this chapter, you’ll just practice the fundamentals. --> ハンズオン形式のプロジェクトに一緒に取り組むことで、Rustの世界に飛び込んでみましょう!  この章ではRustの一般的な概念を、実際のプログラムでの使い方を示しながら紹介します。 -`let`、`match`、メソッド、関連関数、外部クレートの使いかたなどについて学びます!  -これらについての詳細は後続の章で取り上げますので、この章では基本的なところを練習します。 +`let`、`match`、メソッド、関連関数、外部クレートなどについて学びます!  +これらについての詳細は後続の章で取り上げますので、この章では基本的なところだけを練習します。 + @@ -166,8 +175,8 @@ prints it このコードには多くの情報が詰め込まれています。 @@ -180,9 +189,9 @@ standard library, known as `std`: ``` Rustはデフォルトで、標準ライブラリで定義されているアイテムの中のいくつかを、すべてのプログラムのスコープに取り込みます。 @@ -198,8 +207,6 @@ user input. 使いたい型がpreludeにない場合は、その型を`use`文で明示的にスコープに入れる必要があります。 `std::io`ライブラリを`use`すると、ユーザ入力を受け付ける機能など(入出力に関する)多くの便利な機能が利用できるようになります。 -[prelude]: https://doc.rust-lang.org/std/prelude/index.html - `fn`構文は関数を新しく宣言し、かっこの`()`は引数がないことを示し、波括弧の`{`は関数の本体を開始します。 @@ -270,13 +277,15 @@ let apples = 5; この行では`apples`という名前の新しい変数を作成し`5`という値に束縛しています。 -Rustでは変数はデフォルトで不変(immutable)になります。 +Rustでは変数はデフォルトで不変(immutable)で、これは一度変数に値を与えたらその値は変わらないという意味です。 この概念については第3章の[「変数と可変性」][variables-and-mutability]の節で詳しく説明します。 変数を可変(mutable)にするには、変数名の前に`mut`をつけます。 @@ -299,7 +308,7 @@ let mut bananas = 5; // mutable @@ -359,20 +366,19 @@ input: ``` -もし、プログラムの最初に`use std::io`と書いて`io`ライブラリをインポートしていなかったとしても、`std::io::stdin`のように呼び出せば、この関数を利用できます。 +もし、プログラムの最初に`use std::io;`と書いて`io`ライブラリをインポートしていなかったとしても、`std::io::stdin`のように呼び出せば、この関数を利用できます。 `stdin`関数はターミナルの標準入力へのハンドルを表す型である[`std::io::Stdin`][iostdin]のインスタンスを返します。 -[iostdin]: https://doc.rust-lang.org/std/io/struct.Stdin.html - + + + この`&`は、この引数が*参照*であることを示し、これによりコードの複数の部分が同じデータにアクセスしても、そのデータを何度もメモリにコピーしなくて済みます。 参照は複雑な機能(訳注:一部のプログラム言語では正しく使うのが難しい機能)ですが、Rustの大きな利点の一つは参照を安全かつ簡単に使用できることです。 このプログラムを完成させるのに、そのような詳細を知る必要はないでしょう。 @@ -408,15 +417,15 @@ thoroughly.) (参照については第4章でより詳しく説明します) -### `Result`型で失敗の可能性を扱う +### `Result`で失敗の可能性を扱う まだ、このコードの行は終わってません。 @@ -450,44 +459,30 @@ discuss what this line does. -前述したように、`read_line`メソッドは渡された文字列にユーザが入力したものを入れます。 -しかし、同時に値(この場合は[`io::Result`][ioresult])も返します。 -Rustの標準ライブラリには`Result`という名前の型がいくつかあります。 -汎用の[`Result`][result]と、`io::Result`といったサブモジュール用の特殊な型などです。 -これらの`Result`型は[*列挙型*][enums]になります。 -列挙型は*enum*とも呼ばれ、取りうる値として決まった数の*列挙子*(variant)を持ちます。 -列挙型はよく`match`と一緒に使われます。 -これは条件式の一種で、評価時に、列挙型の値がどの列挙子であるかに基づいて異なるコードを実行できるという便利なものです。 - -[ioresult]: https://doc.rust-lang.org/std/io/type.Result.html -[result]: https://doc.rust-lang.org/std/result/enum.Result.html +前述したように、`read_line`メソッドは渡された文字列にユーザが入力したものを入れますが、同時に`Result`値も返します。 +`Result`は[*列挙型*][enums]、または*enum*ともよく呼ばれるもののひとつです。 +列挙型は、複数の取りうる状態の中からどれか一つになることができる型です。 +私たちはこのそれぞれの取りうる状態のことを*列挙子* (variant) と呼びます。 -enumについては第6章で詳しく説明します。 +enumについては[第6章][enums]で詳しく説明します。 これらの`Result`型の目的は、エラー処理に関わる情報を符号化(エンコード)することです。 -[enums]: ch06-00-enums.html - `Result`の列挙子は`Ok`か`Err`です。 @@ -496,25 +491,24 @@ why the operation failed. `Result`型の値にも、他の型と同様にメソッドが定義されています。 -`io::Result`のインスタンスには[`expect`メソッド][expect]がありますので、これを呼び出せます。 -この`io::Result`インスタンスが`Err`の値の場合、`expect`メソッドはプログラムをクラッシュさせ、引数として渡されたメッセージを表示します。 +`Result`のインスタンスには[`expect`メソッド][expect]がありますので、これを呼び出せます。 +この`Result`インスタンスが`Err`の値の場合、`expect`メソッドはプログラムをクラッシュさせ、引数として渡されたメッセージを表示します。 `read_line`メソッドが`Err`を返したら、それはおそらく基礎となるオペレーティング・システムに起因するものでしょう。 -もしこの`io::Result`オブジェクトが`Ok`値の場合、`expect`メソッドは`Ok`列挙子が保持する戻り値を取り出して、その値だけを返してくれます。 +もしこの`Result`オブジェクトが`Ok`値の場合、`expect`メソッドは`Ok`列挙子が保持する戻り値を取り出して、その値だけを返してくれます。 こうして私たちはその値を使うことができるわけです。 今回の場合、その値はユーザ入力のバイト数になります。 -[expect]: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect - @@ -533,13 +527,13 @@ indicating that the program hasn’t handled a possible error. Rustは私たちが`read_line`から返された`Result`値を使用していないことを警告し、これはプログラムがエラーの可能性に対処していないことを示します。 -警告を抑制する正しい方法は実際にエラー処理を書くことです。 +警告を抑制する正しい方法は実際にエラー処理コードを書くことです。 しかし、現時点では問題が起きたときにこのプログラムをクラッシュさせたいだけなので、`expect`が使えるわけです。 エラーからの回復については第9章で学びます。 @@ -563,31 +557,33 @@ the code so far: この行はユーザの入力を現在保持している文字列を表示します。 一組の波括弧の`{}`はプレースホルダーです。 `{}`は値を所定の場所に保持する小さなカニのはさみだと考えてください。 -波括弧をいくつか使えば複数の値を表示できます。 -最初の波括弧の組はフォーマット文字列のあとに並んだ最初の値に対応し、2組目は2番目の値、というように続いていきます。 -一回の`println!`の呼び出しで複数の値を表示するなら次のようになります。 +変数の値を表示するときは、変数名を波括弧の中に入れればよいです。 +式の評価結果を表示するときは、フォーマット文字列の中に空の波括弧を置き、それぞれの空の波括弧プレースホルダに表示する式を同じ順で、カンマ区切りリストにして続けてください。 +一回の`println!`の呼び出しで変数と式の結果を表示するなら次のようになります。 ```rust let x = 5; let y = 10; -println!("x = {} and y = {}", x, y); +println!("x = {x} and y + 2 = {}", y + 2); ``` -このコードは`x = 5 and y = 10`と表示するでしょう。 +このコードは`x = 5 and y + 2 = 12`と表示するでしょう。 ```console $ cargo run @@ -642,8 +643,6 @@ said functionality. Rustの標準ライブラリには、まだ乱数の機能は含まれていません。 ですが、Rustの開発チームがこの機能を持つ[`rand`クレート][randcrate]を提供してくれています。 -[randcrate]: https://crates.io/crates/rand - @@ -653,8 +652,8 @@ Rustの標準ライブラリには、まだ乱数の機能は含まれていま クレートはRustソースコードを集めたものであることを思い出してください。 @@ -666,17 +665,22 @@ programs, and can’t be executed on its own. Cargo’s coordination of external crates is where Cargo really shines. Before we can write code that uses `rand`, we need to modify the *Cargo.toml* file to include the `rand` crate as a dependency. Open that file now and add the -following line to the bottom beneath the `[dependencies]` section header that +following line to the bottom, beneath the `[dependencies]` section header that Cargo created for you. Be sure to specify `rand` exactly as we have here, with -this version number, or the code examples in this tutorial may not work. +this version number, or the code examples in this tutorial may not work: --> Cargoがその力を発揮するのは外部クレートと連携するときです。 `rand`を使ったコードを書く前に、*Cargo.toml*ファイルを編集して`rand`クレートを依存関係に含める必要があります。 そのファイルを開いて、Cargoが作ってくれた`[dependencies]`セクションヘッダの下に次の行を追加してください。 バージョンナンバーを含め、ここに書かれている通り正確に`rand`を指定してください。 -そうしないと、このチュートリアルのコード例が動作しないかもしれません。 +そうしないと、このチュートリアルのコード例が動作しないかもしれません: + *Cargo.toml*ファイルでは、ヘッダに続くものはすべて、他のセクションが始まるまで続くセクションの一部になります。 (訳注:Cargo.tomlファイル内には複数のセクションがあり、各セクションは`[ ]`で囲まれたヘッダ行から始まります) `[dependecies]`はプロジェクトが依存する外部クレートと必要とするバージョンをCargoに伝えます。 -今回は`rand`クレートを`0.8.3`というセマンティックバージョン指定子で指定します。 +今回は`rand`クレートを`0.8.5`というセマンティックバージョン指定子で指定します。 Cargoは[セマンティックバージョニング][semver](*SemVer*と呼ばれることもあります)を理解しており、これはバージョンナンバーを記述するための標準です。 -`0.8.3`という数字は実際には`^0.8.3`の省略記法で、`0.8.3`以上`0.9.0`未満の任意のバージョンを意味します。 -Cargoはこれらのバージョンを、バージョン`0.8.3`と互換性のある公開APIを持つものとみなします。 +`0.8.5`という指定子は実際には`^0.8.5`の省略記法で、0.8.5以上0.9.0未満の任意のバージョンを意味します。 + + + +Cargoはこれらのバージョンを、バージョン0.8.5と互換性のある公開APIを持つものとみなします。 この仕様により、この章のコードが引き続きコンパイルできるようにしつつ、最新のパッチリリースを取得できるようになります。 0.9.0以降のバージョンは、以下の例で使用しているものと同じAPIを持つことを保証しません。 -[semver]: http://semver.org - + ```console $ cargo build Updating crates.io index (crates.ioインデックスを更新しています) - Downloaded rand v0.8.3 - (rand v0.8.3をダウンロードしています) - Downloaded libc v0.2.86 - Downloaded getrandom v0.2.2 + Downloaded rand v0.8.5 + (rand v0.8.5をダウンロードしています) + Downloaded libc v0.2.127 + Downloaded getrandom v0.2.7 Downloaded cfg-if v1.0.0 - Downloaded ppv-lite86 v0.2.10 - Downloaded rand_chacha v0.3.0 - Downloaded rand_core v0.6.2 - Compiling rand_core v0.6.2 - (rand_core v0.6.2をコンパイルしています) - Compiling libc v0.2.86 - Compiling getrandom v0.2.2 + Downloaded ppv-lite86 v0.2.16 + Downloaded rand_chacha v0.3.1 + Downloaded rand_core v0.6.3 + Compiling libc v0.2.127 + (libc v0.2.127をコンパイルしています) + Compiling getrandom v0.2.7 Compiling cfg-if v1.0.0 - Compiling ppv-lite86 v0.2.10 - Compiling rand_chacha v0.3.0 - Compiling rand v0.8.3 + Compiling ppv-lite86 v0.2.16 + Compiling rand_core v0.6.3 + Compiling rand_chacha v0.3.1 + Compiling rand v0.8.5 Compiling guessing_game v0.1.0 (file:///projects/guessing_game) (guessing_game v0.1.0をコンパイルしています) Finished dev [unoptimized + debuginfo] target(s) in 2.53s @@ -758,8 +770,8 @@ adding the rand crate as a dependency もしかしたら異なるバージョンナンバー(とはいえ、SemVerのおかげですべてのコードに互換性があります)や、 @@ -777,8 +789,6 @@ post their open source Rust projects for others to use. レジストリとは[Crates.io][cratesio]のデータのコピーです。 Crates.ioは、Rustのエコシステムにいる人たちがオープンソースのRustプロジェクトを投稿し、他の人が使えるようにする場所です。 -[cratesio]: https://crates.io - *src/main.rs*ファイルを開いて些細な変更を加え、それを保存して再度ビルドすると2行しか表示されません。 + + ```console $ cargo build Compiling guessing_game v0.1.0 (file:///projects/guessing_game) @@ -819,7 +834,7 @@ $ cargo build ``` @@ -837,7 +852,7 @@ reuse what it has already downloaded and compiled for those. Cargo has a mechanism that ensures you can rebuild the same artifact every time you or anyone else builds your code: Cargo will use only the versions of the dependencies you specified until you indicate otherwise. For example, say that -next week version 0.8.4 of the `rand` crate comes out, and that version +next week version 0.8.6 of the `rand` crate comes out, and that version contains an important bug fix, but it also contains a regression that will break your code. To handle this, Rust creates the *Cargo.lock* file the first time you run `cargo build`, so we now have this in the *guessing_game* @@ -846,25 +861,27 @@ directory. Cargoはあなたや他の人があなたのコードをビルドするたびに、同じ生成物をリビルドできるようにするしくみを備えています。 Cargoは何も指示されない限り、指定したバージョンの依存のみを使用します。 -たとえば来週`rand`クレートのバージョン0.8.4が出て、そのバージョンには重要なバグ修正が含まれていますが、同時にあなたのコードを破壊するリグレッションも含まれているとします。 +たとえば来週`rand`クレートのバージョン0.8.6が出て、そのバージョンには重要なバグ修正が含まれていますが、同時にあなたのコードを破壊するリグレッションも含まれているとします。 これに対応するため、Rustは`cargo build`を最初に実行したときに*Cargo.lock*ファイルを作成します。 (いまの*guessing_game*ディレクトリにもあるはずです) プロジェクトを初めてビルドするとき、Cargoは条件に合うすべての依存関係のバージョンを計算し*Cargo.lock*ファイルに書き込みます。 -次にプロジェクトをビルドすると、Cargoは*Cargo.lock*ファイルが存在することを確認し、バージョンを把握するすべての作業を再び行う代わりに、そこで指定されているバージョンを使います。 +次にプロジェクトをビルドすると、Cargoは*Cargo.lock*ファイルが存在することを確認し、バージョンを把握するすべての作業を再び行う代わりに、そこで指定されているバージョンを使うでしょう。 これにより再現性のあるビルドを自動的に行えます。 -言い換えれば、*Cargo.lock*ファイルのおかげで、あなたが明示的にアップグレードするまで、プロジェクトは`0.8.3`を使い続けます。 +言い換えれば、*Cargo.lock*ファイルのおかげで、あなたが明示的にアップグレードするまで、プロジェクトは0.8.5を使い続けます。 +*Cargo.lock*ファイルは再現性のあるビルドのために重要なので、プロジェクトの残りのコードとともにソース管理にチェックインされることが多いです。 クレートを*本当に*アップグレードしたくなったときのために、Cargoは`update`コマンドを提供します。 このコマンドは*Cargo.lock*ファイルを無視して、*Cargo.toml*ファイル内の全ての指定に適合する最新バージョンを算出します。 成功したらCargoはそれらのバージョンを*Cargo.lock*ファイルに記録します。 -ただし、デフォルトでCargoは`0.8.3`以上、`0.9.0`未満のバージョンのみを検索します。 -もし`rand`クレートの新しいバージョンとして`0.8.4`と`0.9.0`の二つがリリースされていたなら、`cargo update`を実行したときに以下のようなメッセージが表示されるでしょう。 +ただし、デフォルトでCargoは0.8.5以上、0.9.0未満のバージョンのみを検索します。 +もし`rand`クレートの新しいバージョンとして0.8.6と0.9.0の二つがリリースされていたなら、`cargo update`を実行したときに以下のようなメッセージが表示されるでしょう。 + + ```console $ cargo update Updating crates.io index (crates.ioインデックスを更新しています) - Updating rand v0.8.3 -> v0.8.4 - (randクレートをv0.8.3 -> v0.8.4に更新しています) + Updating rand v0.8.5 -> v0.8.6 + (randクレートをv0.8.5 -> v0.8.6に更新しています) ``` -Cargoは`0.9.0`リリースを無視します。 -またそのとき、*Cargo.lock*ファイルが変更され、`rand`クレートの現在使用中のバージョンが`0.8.4`になったことにも気づくでしょう。 -そうではなく、`rand`のバージョン`0.9.0`か、`0.9.x`系のどれかを使用するには、*Cargo.toml*ファイルを以下のように変更する必要があります。 +Cargoは0.9.0リリースを無視します。 +またそのとき、*Cargo.lock*ファイルが変更され、`rand`クレートの現在使用中のバージョンが0.8.6になったことにも気づくでしょう。 +そうではなく、`rand`のバージョン0.9.0か、0.9.*x*系のどれかを使用するには、*Cargo.toml*ファイルを以下のように変更する必要があります。 ```toml [dependencies] - rand = "0.9.0" ``` @@ -934,9 +955,6 @@ from a number of packages. いまのところは、これだけ知っていれば十分です。 Cargoはライブラリの再利用をとても簡単にしてくれるので、Rustaceanが数多くのパッケージから構成された小さなプロジェクトを書くことが可能になっています。 -[doccargo]: http://doc.crates.io -[doccratesio]: http://doc.crates.io/crates-io.html - @@ -969,44 +987,42 @@ number リスト2-3:乱数を生成するコードの追加 -まず`use rand::Rng`という行を追加します。 +まず`use rand::Rng;`という行を追加します。 `Rng`トレイトは乱数生成器が実装すべきメソッドを定義しており、それらのメソッドを使用するには、このトレイトがスコープ内になければなりません。 トレイトについて詳しくは第10章で解説します。 次に、途中に2行を追加しています。 最初の行では`rand::thread_rng`関数を呼び出して、これから使う、ある特定の乱数生成器を取得しています。 なお、この乱数生成器は現在のスレッドに固有で、オペレーティングシステムからシード値を得ています。 そして、この乱数生成器の`gen_range`メソッドを呼び出しています。 -このメソッドは`use rand::Rng`文でスコープに導入した`Rng`トレイトで定義されています。 +このメソッドは`use rand::Rng;`文でスコープに導入した`Rng`トレイトで定義されています。 `gen_range`メソッドは範囲式を引数にとり、その範囲内の乱数を生成してくれます。 -ここで使っている範囲式の種類は`開始..終了`という形式で、下限値は含みますが上限値は含みません。 +ここで使っている範囲式の種類は`開始..=終了`という形式で、下限値と上限値をともに含みます。 そのため、1から100までの数をリクエストするには`1..101`と指定する必要があります。 -あるいは、これと同等の`1..=100`という範囲を渡すこともできます。 + ```console $ cargo run Compiling guessing_game v0.1.0 (file:///projects/guessing_game) @@ -1070,8 +1094,8 @@ You should get different random numbers, and they should all be numbers between さて、ユーザ入力と乱数が揃ったので両者を比較してみましょう。 @@ -1106,19 +1130,11 @@ the three outcomes that are possible when you compare two values. `Ordering`もenumの一つで`Less`、`Greater`、`Equal`という列挙子を持っています。 これらは二つの値を比較したときに得られる3種類の結果です。 -```rust,ignore -match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), -} -``` - `match`式は複数の*アーム*(腕)で構成されます。 各アームはマッチさせる*パターン*と、`match`に与えられた値がそのアームのパターンにマッチしたときに実行されるコードで構成されます。 Rustは`match`に与えられた値を受け取って、各アームのパターンを順に照合していきます。 -パターンと`match`式はRustの強力な機能で、コードか遭遇する可能性のあるさまざまな状況を表現し、それらすべてを確実に処理できるようにします。 +パターンと`match`式はRustの強力な機能です: コードか遭遇する可能性のあるさまざまな状況を表現し、それらすべてを確実に処理できるようにします。 これらの機能については、それぞれ第6章と第18章で詳しく説明します。 + +ここで使われている`match`式に対して、例を通して順に見ていきましょう。 +たとえばユーザが50と予想し、今回ランダムに生成された秘密の数字は38だったとしましょう。 + + -ここで使われている`match`式に対して、例を通して順に見ていきましょう。 -たとえばユーザが50と予想し、今回ランダムに生成された秘密の数字は38だったとしましょう。 コードが50と38を比較すると、50は38よりも大きいので`cmp`メソッドは`Ordering::Greater`を返します。 `match`式は`Ordering::Greater`の値を取得し、各アームのパターンを吟味し始めます。 まず最初のアームのパターンである`Ordering::Less`を見て、`Ordering::Greater`の値と`Ordering::Less`がマッチしないことがわかります。 そのため、このアームのコードは無視して、次のアームに移ります。 次のアームのパターンは`Ordering::Greater`で、これは`Ordering::Greater`と*マッチ*します!  このアームに関連するコードが実行され、画面に`Too big!`と表示されます。 -このシナリオでは最後のアームと照合する必要がないため`match`式(の評価)は終了します。 +このシナリオでは最初に成功したマッチで`match`式(の評価)は終了し、最後のアームとは照合されません。 + ```console {{#include ../listings/ch02-guessing-game-tutorial/listing-02-04/output.txt}} ``` @@ -1207,8 +1232,8 @@ Rustのデフォルトは`i32`型で、型情報をどこかに追加してRust 最終的にはプログラムが入力として読み込んだ`String`を実数型に変換し、秘密の数字と数値として比較できるようにしたいわけです。 @@ -1236,19 +1261,19 @@ let guess: u32 = guess.trim().parse().expect("Please type a number!"); `guess`という名前の変数を作成しています。 しかし待ってください、このプログラムには既に`guess`という名前の変数がありませんでしたか?  -たしかにありますが、Rustでは`guess`の前の値を新しい値で*覆い隠す*(shadowする)ことが許されているのです。 -シャドーイング(shadowing)は、`guess_str`と`guess`のような重複しない変数を二つ作る代わりに、`guess`という変数名を再利用させてくれるのです。 -これについては第3章で詳しく説明しますが、今のところ、この機能はある型から別の型に値を変換するときによく使われることを知っておいてください。 +たしかにありますが、Rustでは`guess`の前の値を新しい値で覆い隠す(shadowする)ことが許されているのです。 +*シャドーイング*(shadowing)は、`guess_str`と`guess`のような重複しない変数を二つ作る代わりに、`guess`という変数名を再利用させてくれるのです。 +これについては[第3章][shadowing]で詳しく説明しますが、今のところ、この機能はある型から別の型に値を変換するときによく使われることを知っておいてください。 この新しい変数を`guess.trim().parse()`という式に束縛しています。 @@ -1271,60 +1296,71 @@ class="keystroke">enter results in a carriage return and a newline, これは数値データのみを表現できる`u32`型とこの文字列を比較するために(準備として)行う必要があります。 ユーザは予想を入力したあと`read_line`の処理を終えるためにEnterキーを押す必要がありますが、これにより文字列に改行文字が追加されます。 たとえばユーザが5と入力してEnterキーを押すと、`guess`は`5\n`になります。 -この`\n`は「改行」を表しています。(WindowsではEnterキーを押すとキャリッジリターンと改行が入り`\r\n`となります) +この`\n`は「改行」を表しています。(WindowsではEnterキーを押すとキャリッジリターンと改行が入り`\r\n`となります。) `trim`メソッドは`\n`や`\r\n`を削除するので、その結果`5`だけになります。 -[文字列の`parse`メソッド][parse]は文字列をパース(解析)して何らかの数値にします。 -このメソッドは(文字列を)さまざまな数値型へとパースできるので、`let guess: u32`としてRustに正確な数値型を伝える必要があります。 +[文字列の`parse`メソッド][parse]は文字列を別の型に変換します。 +ここでは、私たちは文字列を数値に変換するために使います。 +`let guess: u32`として、Rustに欲しい数値の正確な型を伝える必要があります。 `guess`の後にコロン(`:`)を付けることで変数の型に注釈をつけることをRustに伝えています。 Rustには組み込みの数値型がいくつかあります。 ここにある`u32`は符号なし32ビット整数で、小さな正の数を表すデフォルトの型に適しています。 -他の数値型については第3章で学びます。 +他の数値型については[第3章][integers]で学びます。 + + + さらに、このサンプルプログラムでは、`u32`という注釈と`secret_number`変数との比較していることから、Rustは`secret_number`変数も`u32`型であるべきだと推論しています。 つまり、いまでは二つの同じ型の値を比較することになるわけです! -[parse]: https://doc.rust-lang.org/std/primitive.str.html#method.parse - `parse`メソッドは論理的に数値に変換できる文字にしか使えないので、よくエラーになります。 たとえば文字列に`A👍%`が含まれていたら数値に変換する術はありません。 解析に失敗する可能性があるため、`parse`メソッドは`read_line`メソッドと同様に`Result`型を返します -([「`Result`型で失敗の可能性を扱う」](#result型で失敗の可能性を扱う)で説明しました)  +([「`Result`で失敗の可能性を扱う」](#resultで失敗の可能性を扱う)で説明しました)  今回も`expect`メソッドを使用して`Result`型を同じように扱います。 `parse`メソッドが文字列から数値を作成できなかったために`Result`型の`Err`列挙子を返したら、`expect`の呼び出しはゲームをクラッシュさせ、私たちが与えたメッセージを表示します。 `parse`が文字列をうまく数値へ変換できたときは`Result`型の`Ok`列挙子を返し、`expect`は`Ok`値から欲しい数値を返してくれます。 -さあ、プログラムを走らせましょう! +さあ、プログラムを走らせましょう: + + ```console $ cargo run @@ -1398,7 +1434,8 @@ which actually introduces a new problem. It doesn’t seem like the user can qui The user could always interrupt the program by using the keyboard shortcut ctrl-c. But there’s another way to escape this insatiable monster, as mentioned in the `parse` discussion in [“Comparing the -Guess to the Secret Number”](#comparing-the-guess-to-the-secret-number): if the user enters a non-number answer, the program will crash. We +Guess to the Secret Number”](#comparing-the-guess-to-the-secret-number) +: if the user enters a non-number answer, the program will crash. We can take advantage of that to allow the user to quit, as shown here: --> @@ -1407,6 +1444,15 @@ can take advantage of that to allow the user to quit, as shown here: ユーザが数字以外の答えを入力すればプログラムはクラッシュします。 それを利用して以下のようにすれば終了できます。 + + ```console $ cargo run Compiling guessing_game v0.1.0 (file:///projects/guessing_game) @@ -1435,8 +1481,8 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` @@ -1511,8 +1557,8 @@ another guess instead of crashing the program @@ -1522,7 +1568,7 @@ method. + ```console $ cargo run Compiling guessing_game v0.1.0 (file:///projects/guessing_game) @@ -1614,17 +1669,17 @@ secret number. Listing 2-6 shows the final code. リスト2-6:数当てゲームの完全なコード -## まとめ +数当てゲームを無事に作り上げることができました。 +おめでとうございます! -数当てゲームを無事に作り上げることができました。 -おめでとうございます! +## まとめ [prelude]: https://doc.rust-lang.org/stable/std/prelude/index.html @@ -1669,7 +1725,6 @@ discusses structs and method syntax, and Chapter 6 explains how enums work. [string]: https://doc.rust-lang.org/stable/std/string/struct.String.html [iostdin]: https://doc.rust-lang.org/stable/std/io/struct.Stdin.html [read_line]: https://doc.rust-lang.org/stable/std/io/struct.Stdin.html#method.read_line -[ioresult]: https://doc.rust-lang.org/stable/std/io/type.Result.html [result]: https://doc.rust-lang.org/stable/std/result/enum.Result.html [enums]: ch06-00-enums.html [expect]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.expect @@ -1677,7 +1732,9 @@ discusses structs and method syntax, and Chapter 6 explains how enums work. [randcrate]: https://crates.io/crates/rand [semver]: http://semver.org [cratesio]: https://crates.io/ -[doccargo]: http://doc.crates.io -[doccratesio]: http://doc.crates.io/crates-io.html +[doccargo]: https://doc.rust-lang.org/cargo/ +[doccratesio]: https://doc.rust-lang.org/cargo/reference/publishing.html [match]: ch06-02-match.html +[shadowing]: ch03-01-variables-and-mutability.html#シャドーイング [parse]: https://doc.rust-lang.org/stable/std/primitive.str.html#method.parse +[integers]: ch03-02-data-types.html#整数型 diff --git a/src/ch03-00-common-programming-concepts.md b/src/ch03-00-common-programming-concepts.md index 6b9f54805..9477e66ed 100644 --- a/src/ch03-00-common-programming-concepts.md +++ b/src/ch03-00-common-programming-concepts.md @@ -27,21 +27,23 @@ them early will give you a strong core to start from. これらの基礎は全てのRustプログラムに存在するものであり、それらを早期に学ぶことにより、強力な基礎を築くことになるでしょう。 -> ### キーワード +> #### キーワード > > Rust言語にも他の言語同様、キーワードが存在し、これらは言語だけが使用できるようになっています。 > これらの単語は、変数や関数名には使えないことを弁えておいてください。ほとんどのキーワードは、特別な意味を持っており、 > 自らのRustプログラムにおいて、様々な作業をこなすために使用することができます; > いくつかは、紐付けられた機能がないものの、将来Rustに追加されるかもしれない機能用に予約されています。 > キーワードの一覧は、付録Aで確認できます。 + +[appendix_a]: appendix-01-keywords.md diff --git a/src/ch03-01-variables-and-mutability.md b/src/ch03-01-variables-and-mutability.md index 77fd81a7d..0172e9a56 100644 --- a/src/ch03-01-variables-and-mutability.md +++ b/src/ch03-01-variables-and-mutability.md @@ -5,32 +5,33 @@ ## 変数と可変性 -第2章で触れた通り、変数は標準で不変になります。これは、 +[「値を変数に保持する」][storing-values-with-variables]の節で触れた通り、変数は標準で不変になります。これは、 Rustが提供する安全性や簡便な並行性の利点を享受する形でコードを書くための選択の1つです。 ところが、まだ変数を可変にするという選択肢も残されています。 どのように、そしてなぜRustは不変性を推奨するのか、さらには、なぜそれとは違う道を選びたくなることがあるのか見ていきましょう。 変数が不変であると、値が一旦名前に束縛されたら、その値を変えることができません。 -これを具体的に説明するために、*projects*ディレクトリに`cargo new --bin variables`コマンドを使って、 -*variables*という名前のプロジェクトを生成しましょう。 +これを具体的に説明するために、*projects*ディレクトリに`cargo new variables`コマンドを使って、 +*variables*という名前のプロジェクトを生成してください。 それから、新規作成した*variables*ディレクトリで、*src/main.rs*ファイルを開き、 @@ -47,11 +48,12 @@ code with the following code that won't compile just yet: ``` -これを保存し、`cargo run`コマンドでプログラムを走らせてください。次の出力に示されているようなエラーメッセージを受け取るはずです: +これを保存し、`cargo run`コマンドでプログラムを走らせてください。 +次の出力に示されているような、不変性に関するエラーメッセージを受け取るはずです: ```console {{#include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt}} @@ -59,68 +61,66 @@ message, as shown in this output: この例では、コンパイラがプログラムに潜むエラーを見つけ出す手助けをしてくれることが示されています。 -コンパイルエラーは、イライラすることもあるものですが、まだプログラムにしてほしいことを安全に行えていないだけということなのです。 +コンパイルエラーは、イライラすることもあるものですが、本当はまだプログラムにしてほしいことを安全に行えていないだけということなのです。 エラーが出るからといって、あなたがいいプログラマではないという意味ではあり*ません*! 経験豊富なRustaceanでも、コンパイルエラーを出すことはあります。 -このエラーは、エラーの原因が`不変変数xに2回代入できない`であると示しています。不変な`x`という変数に別の値を代入しようとしたからです。 +``不変変数`x`に2回代入できません``というエラーメッセージを受け取りました。 +不変な`x`という変数に別の値を代入しようとしたからです。 -以前に不変と指定された値を変えようとした時に、コンパイルエラーが出るのは重要なことです。 +不変と指定された値を変えようとした時に、コンパイルエラーが出るのは重要なことです。 なぜなら、この状況はまさしく、バグに繋がるからです。コードのある部分は、 値が変わることはないという前提のもとに処理を行い、別の部分がその値を変更していたら、 最初の部分が目論見通りに動いていない可能性があるのです。このようなバグは、発生してしまってからでは原因が追いかけづらいものです。 特に第2のコード片が、値を*時々*しか変えない場合、尚更です。 - - - -Rustでは、値が不変であると宣言したら、本当に変わらないことをコンパイラが担保してくれます。 -つまり、コードを読み書きする際に、どこでどうやって値が変化しているかを追いかける必要がなくなります。 +Rustコンパイラは、値が不変であると宣言したら、本当に変わらないことを担保してくれるので、変更を自分で追いかける必要がなくなります。 故にコードを通して正しいことを確認するのが簡単になるのです。 -しかし、可変性は時として非常に有益なこともあります。変数は、標準でのみ、不変です。つまり、 -第2章のように変数名の前に`mut`キーワードを付けることで、可変にできるわけです。この値が変化できるようにするとともに、 -`mut`により、未来の読者に対してコードの別の部分がこの変数の値を変える可能性を示すことで、その意図を汲ませることができるのです。 +しかし可変性は非常に有用で、よりコードを書きやすくしてくれることもあります。 +変数は標準では不変ですが、[第2章][storing-values-with-variables]でやったように、 +変数名の前に`mut`キーワードを付けることで、可変にできるわけです。 +また`mut`を付けることで、コードの別の部分がこの変数の値を変えるだろうと示すことによって、 +未来の読者に対してその意図を汲ませることができるのです。 -例として、*src/main.rs*ファイルを以下のように書き換えてください: +例として、*src/main.rs*ファイルを以下のように書き換えましょう: -`mut`キーワードが使われると、`x`が束縛している値を`5`から`6`に変更できます。 -変数を可変にする方が、不変変数だけがあるよりも書きやすくなるので、変数を可変にしたくなることもあるでしょう。 +`mut`キーワードが使われると、`x`に束縛されている値を`5`から`6`に変更できます。 +可変性を使うかどうかは最終的にはプログラマに任せられており、どちらがより明白と思えるかは個別の状況によるでしょう。 -考えるべきトレードオフはバグの予防以外にも、いくつかあります。例えば、大きなデータ構造を使う場合などです。 -インスタンスを可変にして変更できるようにする方が、いちいちインスタンスをコピーして新しくメモリ割り当てされたインスタンスを返すよりも速くなります。 -小規模なデータ構造なら、新規インスタンスを生成して、もっと関数型っぽいコードを書く方が通して考えやすくなるため、 -低パフォーマンスは、その簡潔性を得るのに足りうるペナルティになるかもしれません。 +### 定数 -### 変数と定数(constants)の違い - - - -変数の値を変更できないようにするといえば、他の多くの言語も持っている別のプログラミング概念を思い浮かべるかもしれません: -*定数*です。不変変数のように、定数は名前に束縛され、変更することが叶わない値のことですが、 +不変変数のように、*定数*(constants)は名前に束縛され、変更することが叶わない値のことですが、 定数と変数の間にはいくつかの違いがあります。 まず、定数には`mut`キーワードは使えません: 定数は標準で不変であるだけでなく、常に不変なのです。 - - - 定数は`let`キーワードの代わりに、`const`キーワードで宣言し、値の型は*必ず*注釈しなければなりません。 -型と型注釈については次のセクション、「データ型」で講義しますので、その詳細について気にする必要はありません。 +型と型注釈については次のセクション、[「データ型」][data-types]で講義しますので、その詳細について気にする必要はありません。 ただ単に型は常に注釈しなければならないのだと思っていてください。 -最後の違いは、定数は定数式にしかセットできないことです。関数呼び出し結果や、実行時に評価される値にはセットできません。 +最後の違いは、定数は定数式にしかセットできないことです。実行時に評価される値にはセットできません。 -定数の名前が`MAX_POINTS`で、値が100,000にセットされた定数定義の例をご覧ください。(Rustの定数の命名規則は、 -全て大文字でアンダースコアで単語区切りすることです): +これが定数定義の例です: ```rust -const MAX_POINTS: u32 = 100_000; +const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3; ``` -定数は、プログラムが走る期間、定義されたスコープ内でずっと有効です。従って、 -プログラムのいろんなところで使用される可能性のあるアプリケーション空間の値を定義するのに有益な選択肢になります。 +定数の名前は`THREE_HOURS_IN_SECONDS`で、その値は60(1分あたりの秒数)×60(1時間あたりの分数)×3(このプログラムで数えたい時間数)の結果にセットされています。 +Rustの定数の命名規則は、全て大文字でアンダースコアで単語区切りすることです。 +コンパイラはコンパイル時に一部の演算を評価することができるので、この定数に10,800という値を設定する代わりに、理解し検証しやすい方法でこの値を書き出すことを選択できます。 +定数宣言内でどの演算が使用できるかについてのさらなる情報は、[Rust Referenceのconstant evaluationの節][const-eval]をお読みください。 + + + +定数は、プログラムが走る期間、定義されたスコープ内でずっと有効です。 +この性質のおかげで、定数はプログラムのいろんなところで使用される可能性のあるアプリケーション空間の値を定義するのに有用です。 例えば、ゲームでプレイヤーが取得可能なポイントの最高値や、光速度などですね。 -第2章の数当てゲームのチュートリアル、「予想と秘密の数字を比較する」節で見たように、前に定義した変数と同じ名前の変数を新しく宣言でき、 -新しい変数は、前の変数を覆い隠します。Rustaceanはこれを最初の変数は、 -2番目の変数に*覆い隠さ*れたと言い、この変数を使用した際に、2番目の変数の値が現れるということです。 +[第2章][comparing-the-guess-to-the-secret-number]の数当てゲームのチュートリアルで見たように、 +前に定義した変数と同じ名前の変数を新しく宣言できます。 +Rustaceanはこれを、最初の変数は2番目の変数に*覆い隠さ*れたと言います。 +これはその変数名を使用した際に、コンパイラは2番目の変数を見るという意味です。 +2番目の変数は実質的に、最初の変数にその影を投げかけ、自身が覆い隠されるかスコープが終了するまで、 +変数名の使用を自身へのものとして扱います。 以下のようにして、同じ変数名を用いて変数を覆い隠し、`let`キーワードの使用を繰り返します: -このプログラムはまず、`x`を`5`という値に束縛します。それから`let x =`を繰り返すことで`x`を覆い隠し、 +このプログラムはまず、`x`を`5`という値に束縛します。それから`let x =`を繰り返すことで新しい変数`x`を作り、 元の値に`1`を加えることになるので、`x`の値は`6`になります。 -3番目の`let`文も`x`を覆い隠し、以前の値に`2`をかけることになるので、`x`の最終的な値は`12`になります。 -括弧を抜けるとシャドーイングは終了し、`x`の値は元の`6`に戻ります。 +次に波括弧によって作られた内側のスコープの中で、3番目の`let`文も`x`を覆い隠して新しい変数を作り、 +以前の値に`2`をかけることになるので、`x`の最終的な値は`12`になります。 +スコープが終わるとシャドーイングは終了し、`x`の値は元の`6`に戻ります。 このプログラムを走らせたら、以下のように出力するでしょう: ```console @@ -304,7 +305,7 @@ When we run this program, it will output the following: ``` `mut`と上書きのもう一つの違いは、再度`let`キーワードを使用したら、実効的には新しい変数を生成していることになるので、 値の型を変えつつ、同じ変数名を使いまわせることです。例えば、 -プログラムがユーザに何らかのテキストに対して空白文字を入力することで何個分のスペースを表示したいかを尋ねますが、 -ただ、実際にはこの入力を数値として保持したいとしましょう: +プログラムがユーザに何らかのテキストに対して空白文字を入力することで何個分のスペースを表示したいかを尋ねて、 +そうしたらこの入力を数値として保持したいとしましょう: ```rust {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/src/main.rs:here}} ``` -この文法要素は、容認されます。というのも、最初の`spaces`変数は文字列型であり、2番目の`spaces`変数は、 -たまたま最初の変数と同じ名前になったまっさらな変数のわけですが、数値型になるからです。故に、シャドーイングのおかげで、 +最初の`spaces`変数は文字列型であり、2番目の`spaces`変数は数値型です。故に、シャドーイングのおかげで、 異なる名前を思いつく必要がなくなるわけです。`spaces_str`と`spaces_num`などですね; 代わりに、 よりシンプルな`spaces`という名前を再利用できるわけです。一方で、この場合に`mut`を使おうとすると、 以下に示した通りですが、コンパイルエラーになるわけです: @@ -352,8 +351,7 @@ try to use `mut` for this, as shown here, we'll get a compile-time error: ``` 変数の型を可変にすることは許されていないと言われているわけです: @@ -368,3 +366,17 @@ can have. --> さあ、変数が動作する方法を見てきたので、今度は変数が取りうるデータ型について見ていきましょう。 + + + +[comparing-the-guess-to-the-secret-number]: +ch02-00-guessing-game-tutorial.html#予想と秘密の数字を比較する +[data-types]: ch03-02-data-types.html#データ型 +[storing-values-with-variables]: ch02-00-guessing-game-tutorial.html#値を変数に保持する +[const-eval]: https://doc.rust-lang.org/reference/const_eval.html diff --git a/src/ch03-02-data-types.md b/src/ch03-02-data-types.md index eb7486ce5..7d8f93849 100644 --- a/src/ch03-02-data-types.md +++ b/src/ch03-02-data-types.md @@ -6,7 +6,7 @@ @@ -18,14 +18,15 @@ Keep in mind that Rust is a *statically typed* language, which means that it must know the types of all variables at compile time. The compiler can usually infer what type we want to use based on the value and how we use it. In cases when many types are possible, such as when we converted a `String` to a numeric -type using `parse` in the “Comparing the Guess to the Secret Number” section in +type using `parse` in the [“Comparing the Guess to the Secret +Number”][comparing-the-guess-to-the-secret-number] section in Chapter 2, we must add a type annotation, like this: --> Rustは*静的型付き*言語であることを弁えておいてください。つまり、 コンパイル時に全ての変数の型が判明している必要があるということです。コンパイラは通常、値と使用方法に基づいて、 使用したい型を推論してくれます。複数の型が推論される可能性がある場合、例えば、 -第2章の「予想と秘密の数字を比較する」節で`parse`メソッドを使って`String`型を数値型に変換した時のように、 +第2章の[「予想と秘密の数字を比較する」][comparing-the-guess-to-the-secret-number]節で`parse`メソッドを使って`String`型を数値型に変換した時のように、 複数の型が可能な場合には、型注釈をつけなければいけません。以下のようにですね: ```rust @@ -33,12 +34,12 @@ let guess: u32 = "42".parse().expect("Not a number!"); // 数字ではあり ``` -ここで型注釈を付けなければ、コンパイラは以下のエラーを表示し、これは可能性のある型のうち、 +上のコード中に示す`: u32`型注釈を付けなければ、コンパイラは以下のエラーを表示し、これは可能性のある型のうち、 どの型を使用したいのかを知るのに、コンパイラがプログラマからもっと情報を得る必要があることを意味します: ```console @@ -63,7 +64,7 @@ integers, floating-point numbers, Booleans, and characters. You may recognize these from other programming languages. Let’s jump into how they work in Rust. --> -スカラー型は、単独の値を表します。Rustには主に4つのスカラー型があります: +*スカラー*型は、単独の値を表します。Rustには主に4つのスカラー型があります: 整数、浮動小数点数、論理値、最後に文字です。他のプログラミング言語でも、これらの型を見かけたことはあるでしょう。 Rustでの動作方法に飛び込みましょう。 @@ -78,15 +79,14 @@ An *integer* is a number without a fractional component. We used one integer type in Chapter 2, the `u32` type. This type declaration indicates that the value it’s associated with should be an unsigned integer (signed integer types start with `i` instead of `u`) that takes up 32 bits of space. Table 3-1 shows -the built-in integer types in Rust. Each variant in the Signed and Unsigned -columns (for example, `i16`) can be used to declare the type of an integer -value. +the built-in integer types in Rust. We can use any of these variants to declare +the type of an integer value. --> -整数とは、小数部分のない数値のことです。第2章で一つの整数型を使用しましたね。`u32`型です。 +*整数*とは、小数部分のない数値のことです。第2章で一つの整数型を使用しましたね。`u32`型です。 この型定義は、紐付けられる値が、符号なし整数(符号付き整数は`u`ではなく、`i`で始まります)になり、 これは、32ビット分のサイズを取ります。表3-1は、Rustの組み込み整数型を表示しています。 -符号付きと符号なし欄の各バリアント(例: `i16`)を使用して、整数値の型を宣言することができます。 +これらのバリアントを使用して、整数値の型を宣言することができます。 | 大きさ | 符号付き | 符号なし | -|--------|---------|---------| -| 8-bit | `i8` | `u8` | -| 16-bit | `i16` | `u16` | -| 32-bit | `i32` | `u32` | -| 64-bit | `i64` | `u64` | -| arch | `isize` | `usize` | +|---------|----------|----------| +| 8-bit | `i8` | `u8` | +| 16-bit | `i16` | `u16` | +| 32-bit | `i32` | `u32` | +| 64-bit | `i64` | `u64` | +| 128-bit | `i128` | `u128` | +| arch | `isize` | `usize` | 各バリアントは、符号付きか符号なしかを選べ、明示的なサイズを持ちます。*符号付き*と*符号なし*は、 -数値が正負を持つかどうかを示します。つまり、数値が符号を持つ必要があるかどうか(符号付き)、または、 +数値が負の数になり得るかどうかを示します。つまり、数値が符号を持つ必要があるかどうか(符号付き)、または、 絶対に正数にしかならず符号なしで表現できるかどうか(符号なし)です。これは、数値を紙に書き下すのと似ています: 符号が問題になるなら、数値はプラス記号、またはマイナス記号とともに表示されます; しかしながら、 その数値が正数であると仮定することが安全なら、符号なしで表示できるわけです。符号付き数値は、 -2の補数表現で保持されます(これが何なのか確信を持てないのであれば、ネットで検索することができます。 -まあ要するに、この解説は、この本の範疇外というわけです)。 +[2の補数][twos-complement]表現で保持されます。 -加えて、`isize`と`usize`型は、プログラムが動作しているコンピュータの種類に依存します: +加えて、`isize`と`usize`型は、表では「arch」と表記していますが、プログラムが動作しているコンピュータのアーキテクチャに依存します: 64ビットアーキテクチャなら、64ビットですし、32ビットアーキテクチャなら、32ビットになります。 整数リテラル(`訳注`: リテラルとは、見たままの値ということ)は、表3-2に示すどの形式でも記述することができます。 -バイトリテラルを除く数値リテラルは全て、 -型接尾辞(例えば、`57u8`)と`_`を見た目の区切り記号(例えば、`1_000`)に付加することができます。 +複数の数値型になることができる数値リテラルは、型を指示するために型接尾辞をつけて、`57u8`のように書くことができます。 +数値リテラルはさらに、数値を読みやすくするために見た目の区切り記号として`_`をつけて、`1_000`のように書くこともできます。 +これは`1000`と指定した場合とまったく同じ値となるでしょう。 -| 数値リテラル | 例 | -|------------------|---------------| +| 数値リテラル | 例 | +|-------------------|---------------| | 10進数 | `98_222` | | 16進数 | `0xff` | | 8進数 | `0o77` | | 2進数 | `0b1111_0000` | -| バイト (`u8`だけ) | `b'A'` | +| バイト (`u8`だけ) | `b'A'` | では、どの整数型を使うべきかはどう把握すればいいのでしょうか?もし確信が持てないのならば、 -Rustの基準型は一般的にいい選択肢になります。整数型の基準は`i32`型です: 64ビットシステム上でも、 -この型が普通最速になります。`isize`と`usize`を使う主な状況は、何らかのコレクションにアクセスすることです。 +Rustの基準型は一般的にいい開始地点になります: 整数型の基準は`i32`型です。 +`isize`と`usize`を使う主な状況は、何らかのコレクションにアクセスすることです。 + + + +> ##### 整数オーバーフロー +> +> `u8`型の変数があるとしましょう。`u8`は0から255までの間の値を取ることができます。 +> この変数を範囲外の値、例えば256に変更しようとすると、*整数オーバーフロー (integer overflow)* が発生し、次の2つのうちのどちらかの挙動になります。 +> デバッグモードでコンパイルしているときは、もしこの挙動が発生したときは実行時にプログラムを*パニック (panic)* させるような、整数オーバーフローのチェックをコンパイラが入れ込みます。 +> プログラムがエラーとともに終了するとき、Rustは*パニック*という用語を使用します; +> パニックについては第9章の[「`panic!`で回復不能なエラー」][unrecoverable-errors-with-panic]でより深く議論します。 +> +> `--release`フラグを付けてリリースモードでコンパイルしているときは、コンパイラはパニックを引き起こす整数オーバーフローチェックを入れ込み*ません*。 +> 代わりに、オーバーフローが起きたときは、プログラムは*2の補数ラップアラウンド (two's complement wrapping)* を行います。 +> 一言で言うと、その型が取ることができる最大値よりも大きい値は、その型が取ることができる最小値に「回り込む」 (“wrap around”) のです。 +> `u8`の場合は、値256は0になり、値257は1になり、という感じです。 +> プログラムはパニックはしなくなるでしょうが、変数が持っている値はおそらくプログラマが期待していたものではないでしょう。 +> 整数オーバーフローのラップアラウンドの挙動に依存するのは、エラーと考えられます。 +> +> オーバーフローが発生する可能性を明示的に取り扱うためには、プリミティブ数値型に関して標準ライブラリが提供する、以下のメソッド群を使うことができます: +> +> * `wrapping_*`メソッド(`wrapping_add`等)で、モードを問わずラップアラウンドさせる。 +> * `checked_*`メソッドで、オーバーフローが発生する場合には`None`値を返す。 +> * `overflowing_*`メソッドで、値と、オーバーフローが発生したかどうかを示す論理値を返す。 +> * `saturating_*`メソッドで、値の最小値または最大値で飽和させる。(訳注: 結果が最大値を上回る場合は最大値に、最小値を下回る場合は最小値にするという意味です) Rustにはさらに、*浮動小数点数*に対しても、2種類の基本型があり、浮動小数点数とは数値に小数点がついたもののことです。 Rustの浮動小数点型は、`f32`と`f64`で、それぞれ32ビットと64ビットサイズです。基準型は`f64`です。 なぜなら、現代のCPUでは、`f32`とほぼ同スピードにもかかわらず、より精度が高くなるからです。 +すべての浮動小数点型は符号付きです。 Rustにも全数値型に期待されうる標準的な数学演算が用意されています: 足し算、引き算、掛け算、割り算、余りです。 -以下の例では、`let`文での各演算の使用方法をご覧になれます: +整数の割り算では、0に近い方の最も近い整数に切り捨てられます。 +以下の例では、`let`文での各数学演算の使用方法をご覧になれます: これらの文の各式は、数学演算子を使用しており、一つの値に評価され、そして、変数に束縛されます。 -付録BにRustで使える演算子の一覧が載っています。 +[付録B][appendix_b]にRustで使える演算子の一覧が載っています。 他の多くの言語同様、Rustの論理値型も取りうる値は二つしかありません: `true`と`false`です。 +論理値のサイズは1バイトです。 Rustの論理値型は、`bool`と指定されます。 例です: @@ -304,12 +368,12 @@ Rustの論理値型は、`bool`と指定されます。 論理値を使う主な手段は、条件式です。例えば、`if`式などですね。`if`式のRustでの動作方法については、 -「制御フロー」節で講義します。 +[「制御フロー」][control-flow]節で講義します。 -ここまで、数値型のみ扱ってきましたが、Rustには文字も用意されています。Rustの`char`型は、 -言語の最も基本的なアルファベット型であり、以下のコードでその使用方法の一例を見ることができます。 -(`char`は、ダブルクォーテーションマークを使用する文字列に対して、シングルクォートで指定されることに注意してください。) +Rustの`char`型は、言語の最も基本的なアルファベット型です。以下は`char`値を宣言するいくつかの例です: -Rustの`char`型は、ユニコードのスカラー値を表します。これはつまり、アスキーよりもずっとたくさんのものを表せるということです。 -アクセント文字; 中国語、日本語、韓国語文字; -絵文字; ゼロ幅スペースは、全てRustでは、有効な`char`型になります。ユニコードスカラー値は、 +`char`リテラルは、ダブルクォーテーションマークを使用する文字列リテラルに対して、シングルクォートで指定することに注意してください。 +Rustの`char`型は4バイトのサイズを持ち、ユニコードのスカラー値を表します。これはつまり、アスキーよりもずっとたくさんのものを表せるということです。 +アクセント記号付き文字; 中国語、日本語、韓国語の文字; +絵文字; ゼロ幅スペースはすべて、Rustでは有効な`char`値です。ユニコードスカラー値は、 `U+0000`から`U+D7FF`までと`U+E000`から`U+10FFFF`までの範囲になります。 ところが、「文字」は実はユニコードの概念ではないので、文字とは何かという人間としての直観は、 -Rustにおける`char`値が何かとは合致しない可能性があります。この話題については、第8章の「文字列」で詳しく議論しましょう。 +Rustにおける`char`値が何かとは合致しない可能性があります。この話題については、第8章の[「文字列でUTF-8でエンコードされたテキストを保持する」][strings]で詳しく議論しましょう。 #### タプル型 -タプルは、複数の型の何らかの値を一つの複合型にまとめ上げる一般的な手段です。 +*タプル*は、様々な型の複数の値を一つの複合型にまとめ上げる汎用的な手段です。 +タプルの長さは固定です: 一度宣言されたらサイズは伸縮できません。 @@ -424,7 +490,7 @@ use pattern matching to destructure a tuple value, like this: @@ -435,13 +501,11 @@ the single tuple into three parts. Finally, the program prints the value of プログラムは`y`変数の値を出力し、`6.4`と表示されます。 -パターンマッチングを通しての分配の他にも、アクセスしたい値の番号をピリオド(`.`)に続けて書くことで、 -タプルの要素に直接アクセスすることもできます。例です: +アクセスしたい値の番号をピリオド(`.`)に続けて書くことで、タプルの要素に直接アクセスすることもできます。例です: -このプログラムは、新しいタプル`x`を作成し、添え字アクセスで各要素に対して新しい変数も作成しています。 +このプログラムは、新しいタプル`x`を作成し、タプルの各要素にそれぞれの添え字を使ってアクセスしています。 多くのプログラミング言語同様、タプルの最初の添え字は0です。 + + +値をひとつも持たないタプルは*ユニット*という特別な名前を持っています。 +この値と、それに対応する型はともに`()`と書き表され、空の値や空の戻り値型を表現します。 +式は、特に値を返さなければ、暗黙的にユニット値を返します。 + @@ -470,21 +545,19 @@ index in a tuple is 0. *配列*によっても、複数の値のコレクションを得ることができます。タプルと異なり、配列の全要素は、 -同じ型でなければなりません。Rustの配列は、他の言語と異なっています。Rustの配列は、 -固定長なのです: 一度宣言されたら、サイズを伸ばすことも縮めることもできません。 +同じ型でなければなりません。一部の他の言語の配列と異なり、Rustの配列は固定長です。 -Rustでは、配列に入れる要素は、角かっこ内にカンマ区切りリストとして記述します: +配列内の要素は、角かっこ内にカンマ区切りリストとして記述します: -配列は、ヒープよりもスタック(スタックとヒープについては第4章で(つまび)らかに議論します)にデータのメモリを確保したい時、 +配列は、ヒープよりもスタック(スタックとヒープについては[第4章][stack-and-heap]で(つまび)らかに議論します)にデータのメモリを確保したい時、 または、常に固定長の要素があることを確認したい時に有効です。 -ただ、配列は、ベクタ型ほど柔軟ではありません。ベクタは、標準ライブラリによって提供されている配列と似たようなコレクション型で、 +ただ、配列は、ベクタ型ほど柔軟ではありません。*ベクタ*は、標準ライブラリによって提供されている配列と似たようなコレクション型で、 こちらは、サイズを伸縮させることが*できます*。配列とベクタ型、どちらを使うべきか確信が持てない時は、 -おそらくベクタ型を使うべきです。第8章でベクタについて詳細に議論します。 +おそらくベクタ型を使うべきです。[第8章][vectors]でベクタについて詳細に議論します。 -ベクタ型よりも配列を使いたくなるかもしれない例は、1年の月の名前を扱うプログラムです。そのようなプログラムで、 -月を追加したり削除したりすることまずないので、配列を使用できます。常に12個要素があることもわかってますからね: +しかしながら、要素数を変えられる必要はないだろうと分かっている場合は、配列のほうが便利です。 +例えば、プログラム中で月の名前を使おうとしているなら、おそらくベクタよりも配列を使うのが良いでしょう。 +常に12個要素があることもわかってますからね: ```rust let months = ["January", "February", "March", "April", "May", "June", "July", @@ -572,12 +647,13 @@ more concise way. ##### 配列の要素にアクセスする -配列は、スタック上に確保される一塊のメモリです。添え字によって、 -配列の要素にこのようにアクセスすることができます: +配列は、あらかじめ知られた固定サイズを持ち、スタック上に確保することができる一塊のメモリです。 +添え字によって、配列の要素にこのようにアクセスすることができます: この例では、`first`という名前の変数には`1`という値が格納されます。配列の`[0]`番目にある値が、 @@ -605,13 +681,13 @@ get the value `2` from index `[1]` in the array. ##### 配列要素への無効なアクセス -配列の終端を越えて要素にアクセスしようとしたら、どうなるでしょうか? -先ほどの例を以下のように変えたとすると、コンパイルは通りますが、実行するとエラーで終了します: +配列の終端を越えて要素にアクセスしようとしたらどうなるか、見てみましょう。 +第2章の数当てゲームと同じようにユーザから配列の添え字を受け取る、次のコードを実行する場合を考えてみてください: -このコードはコンパイルされます。`cargo run`で走らせ、0, 1, 2, 3, または4をこのプログラムに入力すると配列の対応する値を出力します。もし配列の末尾を超えるような、例えば10などの数字を与えると、次のような出力が表示されます。 +このコードはコンパイルされます。`cargo run`で走らせ、`0`, `1`, `2`, `3`, または`4`をこのプログラムに入力すると配列の対応する値を出力します。 +もし配列の末尾を超えるような、例えば`10`などの数字を与えると、次のような出力が表示されます。 ```console -thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 10', src/main.rs:19:19 -スレッド'main'は'範囲外アクセス: 長さは5ですが、添え字は10でした', src/main.rs:19:19 -でパニックしました +thread 'main' panicked at src/main.rs:19:19: +index out of bounds: the len is 5 but the index is 10 +(スレッド'main'はsrc/main.rs:19:19でパニックしました: +範囲外アクセス: 長さは5ですが、添え字は10でした) note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` -コンパイルでは何もエラーが出なかったものの、プログラムは*実行時*エラーに陥り、 -正常終了しませんでした。要素に添え字アクセスを試みると、言語は、 -指定されたその添え字が配列長よりも小さいかを確認してくれます。添え字が配列長よりも大きければ、言語は*パニック*します。 -パニックとは、プログラムがエラーで終了したことを表すRust用語です。 +プログラムは、添え字アクセスで無効な値を使用した時点で*実行時*エラーに陥りました。 +プログラムはエラーメッセージとともに終了し、最後の`println!`文を実行しませんでした。 +要素に添え字アクセスを試みると、言語は、指定されたその添え字が配列長よりも小さいかを確認してくれます。 +添え字が配列長と等しいかより大きければ、言語は*パニック*します。 +この例の場合は特にそうですが、このチェックは実行時に行われなくてはなりません。 +なぜならコンパイラは、ユーザが後でコードを実行したときに、ユーザがどんな値を入力するか知りようがないからです。 -これは、実際に稼働しているRustの安全機構の最初の例になります。低レベル言語の多くでは、 +これは、実際に稼働しているRustのメモリ安全機構の例のひとつになります。低レベル言語の多くでは、 この種のチェックは行われないため、間違った添え字を与えると、無効なメモリにアクセスできてしまいます。 Rustでは、メモリアクセスを許可し、処理を継続する代わりに即座にプログラムを終了することで、 -この種のエラーからプログラマを保護しています。Rustのエラー処理については、第9章でもっと議論します。 +この種のエラーからプログラマを保護しています。第9章ではRustのエラー処理について、そして、 +可読性が高く安全で、パニックもしなければ不正なメモリアクセスも許さないコードをどうすれば書けるのか、もっと議論します。 + + + +[comparing-the-guess-to-the-secret-number]: +ch02-00-guessing-game-tutorial.html#予想と秘密の数字を比較する +[twos-complement]: https://ja.wikipedia.org/wiki/2の補数 +[control-flow]: ch03-05-control-flow.html#制御フロー +[strings]: ch08-02-strings.html#文字列でutf-8でエンコードされたテキストを保持する +[stack-and-heap]: ch04-01-what-is-ownership.html#スタックとヒープ +[vectors]: ch08-01-vectors.html +[unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html +[appendix_b]: appendix-02-operators.md diff --git a/src/ch03-03-how-functions-work.md b/src/ch03-03-how-functions-work.md index 8c16385ff..a15a56588 100644 --- a/src/ch03-03-how-functions-work.md +++ b/src/ch03-03-how-functions-work.md @@ -5,7 +5,7 @@ ## 関数 @@ -36,12 +36,12 @@ Rustの関数と変数の命名規則は、*スネークケース*(`訳注`: som ``` -Rustにおいて関数定義は、`fn`キーワードで始まり、関数名の後に丸かっこの組が続きます。 +Rustでは、`fn`に続けて関数名と丸かっこの組を入力して関数を定義します。 波かっこが、コンパイラに関数本体の開始と終了の位置を伝えます。 定義した関数は、名前に丸かっこの組を続けることで呼び出すことができます。 `another_function`関数がプログラム内で定義されているので、`main`関数内から呼び出すことができるわけです。 ソースコード中で`another_function`を`main`関数の*後*に定義していることに注目してください; 勿論、main関数の前に定義することもできます。コンパイラは、関数がどこで定義されているかは気にしません。 -どこかで定義されていることのみ気にします。 +呼び出し元から見えるスコープ内のどこかで定義されていることのみ気にします。 行出力は、`main`関数内に書かれた順序で実行されています。最初に"Hello, world"メッセージが出て、 それから`another_function`が呼ばれて、こちらのメッセージが出力されています。 -### 関数の引数 +### 引数 -関数は、引数を持つようにも定義できます。引数とは、関数シグニチャの一部になる特別な変数のことです。 -関数に引数があると、引数の位置に実際の値を与えることができます。技術的にはこの実際の値は -*実引数*と呼ばれますが、普段の会話では、仮引数("parameter")と実引数("argument")を関数定義の変数と関数呼び出し時に渡す実際の値、 -両方の意味に区別なく使います(`訳注`: 日本語では、特別区別する意図がない限り、どちらも単に引数と呼ぶことが多いでしょう)。 +関数は、*仮引数 (parameter)* を持つよう定義することもできます。仮引数とは、関数シグニチャの一部になる特別な変数のことです。 +関数に仮引数があると、仮引数に対して具体的な値を与えることができます。 +厳密にはこの具体的な値は*実引数 (argument)* と呼ばれますが、普段の会話では、関数定義内の変数と関数呼び出し時に渡す実際の値の両方の意味で、 +*parameter*と*argument*を区別なく使う傾向にあります (`訳注`: 日本語では、特別区別する意図がない限り、どちらも単に*引数*と呼ぶことが多いでしょう)。 -以下の書き直した`another_function`では、Rustの仮引数がどのようなものかを示しています: +次の版の`another_function`では、仮引数を追加しています: `another_function`の宣言には、`x`という名前の仮引数があります。`x`の型は、 -`i32`と指定されています。値`5`が`another_function`に渡されると、`println!`マクロにより、 -フォーマット文字列中の1組の波かっこがあった位置に値`5`が出力されます。 +`i32`と指定されています。値`5`を`another_function`に渡すと、`println!`マクロにより、 +フォーマット文字列中の`x`を含む1組の波かっこがあった位置に値`5`が出力されます。 関数シグニチャにおいて、各仮引数の型を宣言しなければ*なりません*。これは、Rustの設計において、 -意図的な判断です: 関数定義で型注釈が必要不可欠ということは、コンパイラがその意図するところを推し量るのに、 +意図的な判断です: 関数定義で型注釈が必要不可欠ということは、コンパイラがその意図する型を推し量るのに、 プログラマがコードの他の箇所で使用する必要がないということを意味します。 +コンパイラも、関数が期待する型を知っていれば、より役に立つエラーメッセージを与えることができます。 -関数に複数の仮引数を持たせたいときは、仮引数定義をカンマで区切ってください。 +関数に複数の仮引数を定義したいときは、仮引数定義をカンマで区切ってください。 こんな感じです: -この例では、2引数の関数を生成しています。そして、引数はどちらも`i32`型です。それからこの関数は、 -仮引数の値を両方出力します。関数引数は、全てが同じ型である必要はありません。今回は、 -偶然同じになっただけです。 +この例では、`print_labeled_measurement`という名前の2引数の関数を生成しています。 +第1引数は`value`という名前で`i32`です。第2引数は`unit_label`という名前で`char`型です。 +この関数は`value`と`unit_label`の両方を含むテキストを出力します。 -`x`に対して値`5`、`y`に対して値`6`を渡して関数を呼び出したので、この二つの文字列は、 -この値で出力されました。 +`value`に対して値`5`、`unit_label`に対して値`'h'`を渡して関数を呼び出したので、 +プログラムの出力にはこれらの値が含まれます。 - - -### 関数本体は、文と式を含む +### 文と式 -関数本体は、文が並び、最後に式を置くか文を置くという形で形成されます。現在までには、 -式で終わらない関数だけを見てきたわけですが、式が文の一部になっているものなら見かけましたね。Rustは、式指向言語なので、 +関数本体は、文が並び、最後に式を置くか文を置くという形で形成されます。今のところ、 +私たちが見てきた関数は式で終わることはありませんでしたが、式が文の一部になっているものなら見かけましたね。Rustは、式指向言語なので、 これは理解しておくべき重要な差異になります。他の言語にこの差異はありませんので、文と式がなんなのかと、 その違いが関数本体にどんな影響を与えるかを見ていきましょう。 -実のところ、もう文と式は使っています。*文*とは、なんらかの動作をして値を返さない命令です。 -*式*は結果値に評価されます。ちょっと例を眺めてみましょう。 +* *文 (statement)* はなんらかの動作をして値を返さない命令です。 +* *式 (expression)* は結果値に評価されます。ちょっと例を眺めてみましょう。 +実のところ、もう文と式は使っています。 `let`キーワードを使用して変数を生成し、値を代入することは文になります。 リスト3-1で`let y = 6;`は文です。 @@ -273,7 +272,7 @@ asは前の文にかかるべきだが、大して意味が変わらないので 文は値を返しません。故に、`let`文を他の変数に代入することはできません。 @@ -314,19 +313,19 @@ CやRubyなどの言語とは異なる動作です。CやRubyでは、代入は そうは問屋が卸さないわけです。 -式は何かに評価され、これからあなたが書くRustコードの多くを構成します。 -簡単な数学演算(`5 + 6`など)を思い浮かべましょう。この例は、値`11`に評価される式です。式は文の一部になりえます: +式は値に評価され、これからあなたが書くRustコードの多くを構成します。 +数学演算(`5 + 6`など)を思い浮かべましょう。この例は、値`11`に評価される式です。式は文の一部になりえます: リスト3-1において、`let y = 6`という文の`6`は値`6`に評価される式です。関数呼び出しも式です。マクロ呼び出しも式です。 -新しいスコープを作る際に使用するブロック(`{}`)も式です: +波括弧で作られる新しいスコープも式です: は今回の場合、`4`に評価されるブロックです。その値が、`let`文の一部として`y`に束縛されます。 -今まで見かけてきた行と異なり、文末にセミコロンがついていない`x + 1`の行に気をつけてください。 +今まで見かけてきた行と異なり、`x + 1`の行には文末にセミコロンがついていないことに気をつけてください。 式は終端にセミコロンを含みません。式の終端にセミコロンを付けたら、文に変えてしまいます。そして、文は値を返しません。 次に関数の戻り値や式を見ていく際にこのことを肝に銘じておいてください。 @@ -373,16 +373,16 @@ Keep this in mind as you explore function return values and expressions next. 関数は、それを呼び出したコードに値を返すことができます。戻り値に名前を付けはしませんが、 -矢印(`->`)の後に型を書いて確かに宣言します。Rustでは、関数の戻り値は、関数本体ブロックの最後の式の値と同義です。 +矢印(`->`)の後に型を書いて宣言する必要があります。Rustでは、関数の戻り値は、関数本体ブロックの最後の式の値と同義です。 `return`キーワードで関数から早期リターンし、値を指定することもできますが、多くの関数は最後の式を暗黙的に返します。 こちらが、値を返す関数の例です: @@ -399,7 +399,7 @@ returns a value: @@ -437,7 +437,7 @@ because it’s an expression whose value we want to return. なぜなら、これが返したい値になる式だからです。 もう一つ別の例を見ましょう: @@ -455,7 +455,7 @@ Let's look at another example: このコードを走らせると、`The value of x is: 6`と出力されるでしょう。しかし、 @@ -472,27 +472,27 @@ expression to a statement, we'll get an error: ``` -このコードを実行すると、以下のようにエラーが出ます: +このコードをコンパイルすると、以下のようにエラーが出ます: ```console {{#include ../listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt}} ``` -メインのエラーメッセージである「型が合いません」でこのコードの根本的な問題が明らかになるでしょう。 +メインのエラーメッセージである`mismatched types (型が合いません)`でこのコードの根本的な問題が明らかになるでしょう。 関数`plus_one`の定義では、`i32`型を返すと言っているのに、文は値に評価されないからです。このことは、 -`()`、つまり空のタプルとして表現されています。それゆえに、何も戻り値がなく、これが関数定義と矛盾するので、 +`()`、つまりユニット型として表現されています。それゆえに、何も戻り値がなく、これが関数定義と矛盾するので、 結果としてエラーになるわけです。この出力内で、コンパイラは問題を修正する手助けになりそうなメッセージも出していますね: セミコロンを削除するよう提言しています。そして、そうすれば、エラーは直るわけです。 diff --git a/src/ch03-04-comments.md b/src/ch03-04-comments.md index c3d0ad086..22a08329c 100644 --- a/src/ch03-04-comments.md +++ b/src/ch03-04-comments.md @@ -6,13 +6,13 @@ 全プログラマは、自分のコードがわかりやすくなるよう努めますが、時として追加の説明が許されることもあります。 -このような場合、プログラマは注釈または*コメント*をソースコードに残し、コメントをコンパイラは無視しますが、 +このような場合、プログラマは*コメント*をソースコードに残し、コメントをコンパイラは無視しますが、 ソースコードを読む人間には有益なものと思えるでしょう。 -Rustでは、コメントは2連スラッシュで始め、行の終わりまで続きます。コメントが複数行にまたがる場合、 +Rustの慣用的なコメントスタイルでは、コメントは2連スラッシュで始め、行の終わりまで続きます。コメントが複数行にまたがる場合、 各行に`//`を含める必要があります。こんな感じに: ```rust @@ -48,7 +48,11 @@ Comments can also be placed at the end of lines containing code: コメントは、コードが書かれた行の末尾にも配置することができます: + + +ファイル名: src/main.rs ```rust {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-24-comments-end-of-line/src/main.rs}} @@ -56,11 +60,15 @@ Comments can also be placed at the end of lines containing code: しかし、こちらの形式のコメントの方が見かける機会は多いでしょう。注釈しようとしているコードの1行上に書く形式です: + + ファイル名: src/main.rs ```rust @@ -69,7 +77,10 @@ separate line above the code it's annotating: -Rustには他の種類のコメント、ドキュメントコメントもあり、それについては第14章で議論します。 +Rustには他の種類のコメント、ドキュメントコメントもあり、それについては第14章の[「Crates.ioにクレートを公開する」][publishing]節で議論します。 + +[publishing]: ch14-02-publishing-to-crates-io.html diff --git a/src/ch03-05-control-flow.md b/src/ch03-05-control-flow.md index 71397a24c..aed7faa7b 100644 --- a/src/ch03-05-control-flow.md +++ b/src/ch03-05-control-flow.md @@ -5,15 +5,14 @@ ## 制御フロー -条件が真かどうかによってコードを走らせるかどうかを決定したり、 -条件が真の間繰り返しコードを走らせるか決定したりすることは、多くのプログラミング言語において、基本的な構成ブロックです。 +条件が`true`かどうかによってコードを走らせたり、 +条件が`true`の間繰り返しコードを走らせたりできることは、多くのプログラミング言語において、基本的な構成ブロックです。 Rustコードの実行フローを制御する最も一般的な文法要素は、`if`式とループです。 @@ -50,31 +49,27 @@ the `if` expression. In the *src/main.rs* file, input the following: ``` - - `if`式は全て、キーワードの`if`から始め、条件式を続けます。今回の場合、 条件式は変数`number`が5未満の値になっているかどうかをチェックします。 -条件が真の時に実行したい一連のコードを条件式の直後に波かっこで包んで配置します。`if`式の条件式と紐付けられる一連のコードは、 +条件が`true`の時に実行する一連のコードを条件式の直後に波かっこで包んで配置します。`if`式の条件式と紐付けられる一連のコードは、 時として*アーム*と呼ばれることがあります。 -第2章の「予想と秘密の数字を比較する」の節で議論した`match`式のアームと同じです。 +第2章の[「予想と秘密の数字を比較する」][comparing-the-guess-to-the-secret-number]の節で議論した`match`式のアームと同じです。 @@ -180,11 +175,11 @@ Running this code will print `number was something other than zero`. #### `else if`で複数の条件を扱う -`if`と`else`を組み合わせて`else if`式にすることで複数の条件を持たせることもできます。例です: +`if`と`else`を組み合わせて`else if`式にすることで複数の条件を使うこともできます。例です: -このプログラムを実行すると、`if`式が順番に吟味され、最初に条件が真になった本体が実行されます。 +このプログラムを実行すると、`if`式が順番に吟味され、最初に条件が`true`に評価された本体が実行されます。 6は2で割り切れるものの、`number is devisible by 2`や、 `else`ブロックの`number is not divisible by 4, 3, or 2`という出力はされないことに注目してください。 -それは、Rustが最初の真条件のブロックのみを実行し、 +それは、Rustが最初の`true`な条件のブロックのみを実行し、 条件に合ったものが見つかったら、残りはチェックすらしないからです。 -`if`は式なので、`let`文の右辺に持ってくることができます。リスト3-2のようにですね。 +`if`は式なので、`let`文の右辺に持ってきて結果を変数に代入することができます。リスト3-2のようにですね。 + リスト3-2: `if`式の結果を変数に代入する @@ -278,7 +275,7 @@ whole `if` expression depends on which block of code executes. This means the values that have the potential to be results from each arm of the `if` must be the same type; in Listing 3-2, the results of both the `if` arm and the `else` arm were `i32` integers. If the types are mismatched, as in the following -example, we'll get an error: +example, we’ll get an error: --> 一連のコードは、そのうちの最後の式に評価され、数値はそれ単独でも式になることを思い出してください。 @@ -313,17 +310,17 @@ find the problem in the program: `if`ブロックの式は整数に評価され、`else`ブロックの式は文字列に評価されます。これでは動作しません。 -変数は単独の型でなければならないからです。コンパイラは、コンパイル時に`number`変数の型を確実に把握する必要があるため、 -コンパイル時に`number`が使われている箇所全部で型が有効かどうか検査することができるのです。 +変数は単独の型でなければならず、コンパイラは、コンパイル時に`number`変数の型を確実に把握する必要があるからです。 +`number`の型を把握していることで、コンパイラは、コンパイル時に`number`が使われている箇所全部で型が有効であるか検証できるのです。 `number`の型が実行時にしか決まらないのであれば、コンパイラはそれを実行することができなくなってしまいます; どの変数に対しても、架空の複数の型があることを追いかけなければならないのであれば、コンパイラはより複雑になり、 コードに対して行える保証が少なくなってしまうでしょう。 @@ -336,9 +333,9 @@ multiple hypothetical types for any variable. 一連のコードを1回以上実行できると、しばしば役に立ちます。この作業用に、 @@ -384,19 +381,25 @@ like this: このプログラムを実行すると、プログラムを手動で止めるまで、何度も何度も続けて`again!`と出力するでしょう。 ほとんどの端末でctrl-cというショートカットが使え、 -永久ループに囚われてしまったプログラムを終了させられます。試しにやってみましょう: +永久ループに囚われてしまったプログラムに割り込むことができます。試しにやってみましょう: + + ```console $ cargo run Compiling loops v0.1.0 (file:///projects/loops) - Finished dev [unoptimized + debuginfo] target(s) in 0.29 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.29s Running `target/debug/loops` again! again! @@ -406,25 +409,27 @@ again! ``` `^C`という記号が出た場所が、ctrl-cを押した場所です。`^C`の後には`again!`と表示されたり、 -されなかったりします。ストップシグナルをコードが受け取った時にループのどこにいたかによります。 +されなかったりします。割り込みシグナルをコードが受け取った時にループのどこにいたかによります。 -幸いなことに、Rustにはループを抜け出す別のより信頼できる手段があります。 +幸いなことに、Rustにはコードによってループを抜け出す手段もあります。 ループ内に`break`キーワードを配置することで、プログラムに実行を終了すべきタイミングを教えることができます。 -第2章の「正しい予想をした後に終了する」節の数当てゲーム内でこれをして、ユーザが予想を的中させ、 +第2章の[「正しい予想をした後に終了する」][quitting-after-a-correct-guess]節の数当てゲーム内でこれをして、ユーザが予想を的中させ、 ゲームに勝った時にプログラムを終了させたことを思い出してください。 + +#### ループから値を返す + + + +`loop`の使用法のひとつとして、失敗するかもしれないと分かっている操作、 +例えばスレッドがそのジョブを完了したかを確認する操作などを、リトライするというのがあります。 +さらに、コードの他の部分で使うために、ループの外に操作の結果を渡す必要があるかもしれません。 +これを行うには、ループを止めるために使っている`break`式の後ろに、返したい値を付け加えてください; +その値はループを抜けて返され、使うことができます。このように: + +```rust +{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs}} +``` + + + +ループの前で`counter`という変数を宣言し、`0`に初期化しています。 +次に、ループから返された値を保持するために、`result`という変数を宣言しています。 +ループの繰り返しごとに、`counter`変数に`1`を追加し、`counter`が`10`に等しいかチェックします。 +等しい場合は、値`counter * 2`とともに`break`キーワードを使用しています。 +ループの後には、値を`result`に代入する文を終了するためのセミコロンが使われています。 +最後に、`result`の値を出力していて、この場合は`20`です。 + + + +#### 複数のループを区別するループラベル + ループ内にループがある場合、`break`と`continue`は最も内側のループに適用されます。 *ループラベル*を使用することで、`break`や`continue`が適用されるループを指定することができます。 +ループラベルはシングルクオートで始める必要があります。 以下に例を示します。 @@ -477,28 +531,23 @@ doesn’t specify a label will exit the inner loop only. The `break #### `while`で条件付きループ -プログラムにとってループ内で条件式を評価できると、有益なことがしばしばあります。条件が真の間、 -ループが走るわけです。条件が真でなくなった時にプログラムは`break`を呼び出し、ループを終了します。 -このタイプのループは、`loop`、`if`、`else`、`break`を組み合わせることでも実装できます; +プログラムは、ループ内で条件式を評価することがよく必要になるでしょう。条件が`true`の間、 +ループが走るわけです。条件が`true`でなくなった時にプログラムは`break`を呼び出し、ループを終了します。 +このような挙動は、`loop`、`if`、`else`、`break`を組み合わせることでも実装できます; お望みなら、プログラムで今、試してみるのもいいでしょう。 - - - しかし、このパターンは頻出するので、Rustにはそれ用の文法要素が用意されていて、`while`ループと呼ばれます。 -リスト3-3は、`while`を使用しています: プログラムは3回ループし、それぞれカウントダウンします。 -それから、ループ後に別のメッセージを表示して終了します: +リスト3-3では、プログラムを3回ループさせるために`while`を使用しています。 +繰り返しごとにカウントダウンして、ループ後にメッセージを表示して終了します。 この文法要素により、`loop`、`if`、`else`、`break`を使った時に必要になるネストがなくなり、 -より明確になります。条件が真の間、コードは実行されます; そうでなければ、ループを抜けます. +より明確になります。条件が`true`に評価される間、コードは実行されます; そうでなければ、ループを抜けます. -`while`要素を使って配列などのコレクションの要素を覗き見ることができます。例えば、リスト3-4を見ましょう。 +配列などのコレクションの要素を覗き見るために、`while`要素を使うこともできます。 +例えば、リスト3-4のループは配列`a`の各要素を出力します。 ここで、コードは配列の要素を順番にカウントアップして覗いています。番号0から始まり、 -配列の最終番号に到達するまでループします(つまり、`index < 5`が真でなくなる時です)。 +配列の最終番号に到達するまでループします(つまり、`index < 5`が`true`でなくなる時です)。 このコードを走らせると、配列内の全要素が出力されます: ```console @@ -581,23 +632,26 @@ to fetch a sixth value from the array. 配列から6番目の値を拾おうとする前にループは実行を終了します。 -しかし、このアプローチは間違いが発生しやすいです; 添え字の長さが間違っていれば、 -プログラムはパニックしてしまいます。また遅いです。 -コンパイラが実行時にループの各回ごとに境界値チェックを行うようなコードを追加するからです。 +しかし、このアプローチは間違いが発生しやすいです; 添え字の値や判定条件が間違っていれば、 +プログラムはパニックしてしまいます。例えば、`a`配列の定義を4要素を持つように変更したのに、 +条件を`while index < 4`に更新し忘れた場合、コードはパニックするでしょう。また遅いです。 +実行時にループの各回ごとに添字が配列の境界内にあるかチェックするコードを、コンパイラが追加するからです。 -より効率的な対立案として、`for`ループを使ってコレクションの各アイテムに対してコードを実行することができます。 -`for`ループはリスト3-5のこんな見た目です。 +より簡潔な対立案として、`for`ループを使ってコレクションの各アイテムに対してコードを実行することができます。 +`for`ループはリスト3-5のコードのようになります。 -例えば、リスト3-4のコードで、`a`配列からアイテムを1つ削除したのに、条件式を`while index < 4`にするのを忘れていたら、 -コードはパニックします。`for`ループを使っていれば、配列の要素数を変えても、 -他のコードをいじることを覚えておく必要はなくなるわけです。 +`for`ループを使っていれば、配列の要素数を変えても、 +リスト3-4で使った方法のように他のコードをいじることを覚えておく必要はなくなるわけです。 `for`ループのこの安全性と簡潔性により、Rustで使用頻度の最も高いループになっています。 リスト3-3で`while`ループを使ったカウントダウンサンプルのように、一定の回数、同じコードを実行したいような状況であっても、 多くのRustaceanは、`for`ループを使うでしょう。どうやってやるかといえば、 -`Range`型を使うのです。Range型は、標準ライブラリで提供される片方の数字から始まって、 +標準ライブラリで提供される`Range`型を使うのです。`Range`型は、片方の数字から始まって、 もう片方の数字未満の数値を順番に生成する型です。 やりましたね!結構長い章でした: 変数、スカラー値と複合データ型、関数、コメント、`if`式、そして、ループについて学びました! -この章で議論した概念について経験を積みたいのであれば、以下のことをするプログラムを組んでみてください: +この章で議論した概念について経験を積むために、以下のことをするプログラムを組んでみてください: * 温度を華氏と摂氏で変換する。 -* フィボナッチ数列のn番目を生成する。 +* フィボナッチ数列の*n*番目を生成する。 * クリスマスキャロルの定番、"The Twelve Days of Christmas"の歌詞を、 曲の反復性を利用して出力する。 @@ -711,3 +763,15 @@ commonly exist in other programming languages: ownership. --> 次に進む準備ができたら、他の言語にはあまり存在*しない*Rustの概念について話しましょう: 所有権です。 + + + +[comparing-the-guess-to-the-secret-number]: +ch02-00-guessing-game-tutorial.html#予想と秘密の数字を比較する +[quitting-after-a-correct-guess]: +ch02-00-guessing-game-tutorial.html#正しい予想をした後に終了する diff --git a/src/ch04-00-understanding-ownership.md b/src/ch04-00-understanding-ownership.md index 220d4a1b1..a3bf3029e 100644 --- a/src/ch04-00-understanding-ownership.md +++ b/src/ch04-00-understanding-ownership.md @@ -5,13 +5,14 @@ # 所有権を理解する -所有権はRustの最もユニークな機能であり、これのおかげでガベージコレクタなしで安全性担保を行うことができるのです。 -故に、Rustにおいて、所有権がどう動作するのかを理解するのは重要です。この章では、所有権以外にも、関連する機能を +所有権はRustの最もユニークな機能であり、それ以外の言語機能と深く関連しています。 +所有権のおかげで、Rustはガベージコレクタの必要なしにメモリ安全性を担保することができていて、 +そのため所有権の仕組みを理解しておくことが重要です。この章では、所有権以外にも、関連する機能を いくつか話していきます: 借用、スライス、そして、コンパイラがデータをメモリにどう配置するかです。 diff --git a/src/ch04-01-what-is-ownership.md b/src/ch04-01-what-is-ownership.md index 2733433d8..9ee58b4ff 100644 --- a/src/ch04-01-what-is-ownership.md +++ b/src/ch04-01-what-is-ownership.md @@ -5,38 +5,38 @@ ## 所有権とは? -Rustの中心的な機能は、*所有権*です。この機能は、説明するのは簡単なのですが、言語の残りの機能全てにかかるほど -深い裏の意味を含んでいるのです。 +*所有権*とは、Rustプログラムがメモリをどのように管理するかを支配している、規則の集合です。 全てのプログラムは、実行中にコンピュータのメモリの使用方法を管理する必要があります。プログラムが動作するにつれて、 定期的に使用されていないメモリを検索するガベージコレクションを持つ言語もありますが、他の言語では、 プログラマが明示的にメモリを確保したり、解放したりしなければなりません。Rustでは第3の選択肢を取っています: -メモリは、コンパイラがコンパイル時にチェックする一定の規則とともに所有権システムを通じて管理されています。 -どの所有権機能も、実行中にプログラムの動作を遅くすることはありません。 +メモリは、コンパイラがチェックする一定の規則とともに所有権システムを通じて管理されています。 +規則のうちどれかひとつにでも違反すれば、プログラムはコンパイルできないでしょう。 +どの所有権機能も、実行中にプログラムの動作を遅くすることはないでしょう。 所有権は多くのプログラマにとって新しい概念なので、慣れるまでに時間がかかります。 -嬉しいことに、Rustと、所有権システムの規則の経験を積むと、より自然に安全かつ効率的なコードを構築できるようになります。 +嬉しいことに、Rustと、所有権システムの規則の経験を積んでいくにつれて、 +自然に安全かつ効率的なコードを構築するのはだんだん簡単だと思えるようになるでしょう。 その調子でいきましょう! - - - - - - - - - - - - - - - - - > ### スタックとヒープ > > 多くのプログラミング言語において、スタックとヒープについて考える機会はそう多くないでしょう。 > しかし、Rustのようなシステムプログラミング言語においては、値がスタックに積まれるかヒープに置かれるかは、 -> 言語の振る舞い方や、特定の決断を下す理由などに影響以上のものを与えるのです。 +> 言語の振る舞いや、特定の決断を下す理由などに影響を与えるのです。 > この章の後半でスタックとヒープを交えて所有権の一部が解説されるので、ここでちょっと予行演習をしておきましょう。 > > スタックもヒープも、実行時にコードが使用できるメモリの一部になりますが、異なる手段で構成されています。 @@ -147,23 +130,24 @@ PROD: START BOX > 途中や一番下に追加したり、取り除いたりすることもできません。データを追加することは、 > *スタックにpushする*といい、データを取り除くことは、*スタックからpopする*と表現します(`訳注`: > 日本語では単純に英語をそのまま活用してプッシュ、ポップと表現するでしょう)。 +> スタック上のデータは全て既知の固定サイズでなければなりません。 +> コンパイル時にサイズがわからなかったり、サイズが可変のデータについては、代わりにヒープに格納しなければなりません。 > -> データへのアクセス方法のおかげで、スタックは高速です: 新しいデータを置いたり、 -> データを取得する場所を探す必要が絶対にないわけです。というのも、その場所は常に一番上だからですね。 -> スタックを高速にする特性は他にもあり、それはスタック上のデータは全て既知の固定サイズでなければならないということです。 -> -> コンパイル時にサイズがわからなかったり、サイズが可変のデータについては、代わりにヒープに格納することができます。 > ヒープは、もっとごちゃごちゃしています: ヒープにデータを置く時、あるサイズのスペースを求めます。 -> OSはヒープ上に十分な大きさの空の領域を見つけ、使用中にし、*ポインタ*を返します。ポインタとは、その場所へのアドレスです。 -> この過程は、*ヒープに領域を確保する(allocating on the heap)*と呼ばれ、時としてそのフレーズを単に*allocateする*などと省略したりします。 +> メモリアロケータはヒープ上に十分な大きさの空の領域を見つけ、使用中にし、*ポインタ*を返します。ポインタとは、その場所へのアドレスです。 +> この過程は、*ヒープに領域を確保する (allocating on the heap)* と呼ばれ、時としてそのフレーズを単に*allocateする*などと省略したりします > (`訳注`: こちらもこなれた日本語訳はないでしょう。allocateは「メモリを確保する」と訳したいところですが) -> スタックに値を積むことは、メモリ確保とは考えられません。ポインタは、既知の固定サイズなので、 +> (スタックに値を積むことは、メモリ確保とは考えられません)。ヒープへのポインタは、既知の固定サイズなので、 > スタックに保管することができますが、実データが必要になったら、ポインタを追いかける必要があります。 -> > レストランで席を確保することを考えましょう。入店したら、グループの人数を告げ、 > 店員が全員座れる空いている席を探し、そこまで誘導します。もしグループの誰かが遅れて来るのなら、 > 着いた席の場所を尋ねてあなたを発見することができます。 > +> スタックにデータを積むほうが、ヒープ上にメモリを確保するより高速です。 +> アロケータが新しいデータを置くための場所を探さなくていいからです。というのも、その場所は常にスタックの一番上だからですね。 +> それと比べて、ヒープ上にメモリを確保するのはより手間の多い仕事です。 +> アロケータはまずデータを入れるのに充分な大きさの場所を探して、そして次のメモリ確保に備えて予約をしないといけないからです。 +> > ヒープへのデータアクセスは、スタックのデータへのアクセスよりも低速です。 > ポインタを追って目的の場所に到達しなければならないからです。現代のプロセッサは、メモリをあちこち行き来しなければ、 > より速くなります。似た例えを続けましょう。レストランで多くのテーブルから注文を受ける給仕人を考えましょう。最も効率的なのは、 @@ -171,7 +155,7 @@ PROD: START BOX > それからテーブルBの注文、さらにまたA、それからまたBと渡り歩くのは、かなり低速な過程になってしまうでしょう。 > 同じ意味で、プロセッサは、 > データが隔離されている(ヒープではそうなっている可能性がある)よりも近くにある(スタックではこうなる)ほうが、 -> 仕事をうまくこなせるのです。ヒープに大きな領域を確保する行為も時間がかかることがあります。 +> 仕事をうまくこなせるのです。 > > コードが関数を呼び出すと、関数に渡された値(ヒープのデータへのポインタも含まれる可能性あり)と、 > 関数のローカル変数がスタックに載ります。関数の実行が終了すると、それらの値はスタックから取り除かれます。 @@ -179,12 +163,8 @@ PROD: START BOX > どの部分のコードがどのヒープ上のデータを使用しているか把握すること、ヒープ上の重複するデータを最小化すること、 > メモリ不足にならないようにヒープ上の未使用のデータを掃除することは全て、所有権が解決する問題です。 > 一度所有権を理解したら、あまり頻繁にスタックとヒープに関して考える必要はなくなるでしょうが、 -> ヒープデータを管理することが所有権の存在する理由だと知っていると、所有権がありのままで動作する理由を -> 説明するのに役立つこともあります。 +> 所有権の主な目的はヒープデータを管理することだと知っていると、所有権がどうしてこうなっているのか説明するのに役立つこともあります。 > - -まず、所有権のルールについて見ていきましょう。 -この規則を具体化する例を扱っていく間もこれらのルールを肝に銘じておいてください: +まず、所有権の規則について見ていきましょう。 +この規則を具体化する例を扱っていく間もこれらの規則を肝に銘じておいてください: -* Rustの各値は、*所有者*と呼ばれる変数と対応している。 +* Rustの各値には、*所有者*が存在する。 * いかなる時も所有者は一つである。 * 所有者がスコープから外れたら、値は破棄される。 @@ -217,27 +197,25 @@ work through the examples that illustrate them: ### 変数スコープ -第2章で、Rustプログラムの例はすでに見ています。もう基本的な記法は通り過ぎたので、 -`fn main() {`というコードはもう例に含みません。従って、例をなぞっているなら、 -これからの例は`main`関数に手動で入れ込まなければいけなくなるでしょう。結果的に、例は少々簡潔になり、 -定型コードよりも具体的な詳細に集中しやすくなります。 +もう基本的なRustの文法は通り過ぎたので、`fn main() {`というコードはもう例に含みません。 +従って、例をなぞっているなら、これからの例は`main`関数に手動で入れ込むようにしてください。 +結果的に、例は少々簡潔になり、定型コードよりも具体的な詳細に集中しやすくなります。 所有権の最初の例として、何らかの変数の*スコープ*について見ていきましょう。スコープとは、 -要素が有効になるプログラム内の範囲のことです。以下のような変数があるとしましょう: +要素が有効になるプログラム内の範囲のことです。以下の変数を例に取ります: ```rust let s = "hello"; @@ -246,37 +224,23 @@ let s = "hello"; 変数`s`は、文字列リテラルを参照し、ここでは、文字列の値はプログラムのテキストとしてハードコードされています。 この変数は、宣言された地点から、現在の*スコープ*の終わりまで有効になります。リスト4-1には、 -変数`s`が有効な場所に関する注釈がコメントで付記されています。 +変数`s`が有効な場所に関する注釈がコメントで付記されたプログラムを示します。 - +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}} +``` -```rust -{ // sは、ここでは有効ではない。まだ宣言されていない - let s = "hello"; // sは、ここから有効になる - - // sで作業をする -} // このスコープは終わり。もうsは有効ではない -``` - - - リスト4-1: 変数と有効なスコープ -* `s`が*スコープに入る*と、有効になる -* *スコープを抜ける*まで、有効なまま +* `s`がスコープに*入る*と、有効になる。 +* スコープを*抜ける*まで、有効なまま。 -ここで、スコープと変数が有効になる期間の関係は、他の言語に類似しています。さて、この理解のもとに、 +今のところ、スコープと、変数が有効である期間の関係は、他の言語のそれに類似しています。さて、この理解のもとに、 `String`型を導入して構築していきましょう。 - -所有権の規則を具体化するには、第3章の「データ型」節で講義したものよりも、より複雑なデータ型が必要になります。 -以前講義した型は全てスタックに保管され、スコープが終わるとスタックから取り除かれますが、 -ヒープに確保されるデータ型を観察して、 +than those we covered in the [“Data Types”][data-types] section +of Chapter 3. The types covered previously are of a known size, can be stored +on the stack and popped off the stack when their scope is over, and can be +quickly and trivially copied to make a new, independent instance if another +part of code needs to use the same value in a different scope. But we want to +look at data that is stored on the heap and explore how Rust knows when to +clean up that data, and the `String` type is a great example. +--> + +所有権の規則を具体化するには、第3章の[「データ型」][data-types]節で講義したものよりも、より複雑なデータ型が必要になります。 +以前講義した型は、既知のサイズを持ち、スタックに置いておいてスコープが終わるとスタックから取り除かれるという扱いが可能でした。 +さらに、コードの別の場所で同じ値を異なるスコープを持たせて使う必要があるなら、 +新しい、独立したインスタンスに、高速に、そして自明にコピーすることができました。 +が、ヒープに確保されるデータ型を観察して、 コンパイラがどうそのデータを掃除すべきタイミングを把握しているかを掘り下げていきたいと思います。 +`String`型はその好例です。 -ここでは、例として`String`型を使用し、`String`型の所有権にまつわる部分に着目しましょう。 -また、この観点は、標準ライブラリや自分で生成する他の複雑なデータ型にも適用されます。 -`String`型については、第8章でより深く議論します。 +`String`型の所有権にまつわる部分に着目しましょう。 +またこの観点は、標準ライブラリから提供されたか自分で作成したかを問わず、他の複雑なデータ型にも適用されます。 +`String`型については、[第8章][ch8]でより深く議論します。 既に文字列リテラルは見かけましたね。文字列リテラルでは、文字列の値はプログラムにハードコードされます。 @@ -357,51 +327,35 @@ let s = String::from("hello"); ``` -この二重コロンは、`string_from`などの名前を使うのではなく、 -`String`型直下の`from`関数を特定する働きをする演算子です。この記法について詳しくは、 -第5章の「メソッド記法」節と、第7章の「モジュール定義」でモジュールを使った名前空間分けについて話をするときに議論します。 +この二重コロン`::`演算子は、`string_from`などの名前を使うのではなく、 +`String`型直下の`from`関数を特定する働きをします。この記法について詳しくは、 +第5章の[「メソッド記法」][method-syntax]節と、第7章の[「モジュールツリーの要素を示すためのパス」][paths-module-tree]でモジュールを使った名前空間分けについて話をするときに議論します。 -この種の文字列は、可変化することが*できます*: +この種の文字列は、変更することが*できます*: - - - - - -```rust -let mut s = String::from("hello"); - -s.push_str(", world!"); // push_str()関数は、リテラルをStringに付け加える - -println!("{}", s); // これは`hello, world!`と出力する -``` -では、ここでの違いは何でしょうか?なぜ、`String`型は可変化できるのに、リテラルはできないのでしょうか? +では、ここでの違いは何でしょうか?なぜ、`String`型は変更できるのに、リテラルはできないのでしょうか? 違いは、これら二つの型がメモリを扱う方法にあります。 @@ -434,13 +388,13 @@ to hold the contents. This means: ヒープに確保して内容を保持します。つまり: -* メモリは、実行時にOSに要求される。 -* `String`型を使用し終わったら、OSにこのメモリを返還する方法が必要である。 +* メモリは、実行時にメモリアロケータに要求される。 +* `String`型を使用し終わったら、アロケータにこのメモリを返還する方法が必要である。 - - - ```rust -{ - let s = String::from("hello"); // sはここから有効になる - - // sで作業をする -} // このスコープはここでおしまい。sは - // もう有効ではない +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs:here}} ``` -`String`型が必要とするメモリをOSに返還することが自然な地点があります: `s`変数がスコープを抜ける時です。 -変数がスコープを抜ける時、Rustは特別な関数を呼んでくれます。この関数は、`drop`と呼ばれ、 +`String`型が必要とするメモリをアロケータに返還することが自然な地点があります: `s`変数がスコープを抜ける時です。 +変数がスコープを抜ける時、Rustは特別な関数を呼んでくれます。この関数は、[`drop`][drop]と呼ばれ、 ここに`String`型の書き手はメモリを返還するコードを配置することができます。Rustは、閉じ波括弧で自動的に`drop`関数を呼び出します。 > 注釈: C++では、要素の生存期間の終了地点でリソースを解放するこのパターンを時に、 @@ -540,11 +478,16 @@ we’ve allocated on the heap. Let’s explore some of those situations now. ヒープ上に確保されたデータを複数の変数に使用させるようなもっと複雑な場面では、コードの振る舞いは、 予期しないものになる可能性もあります。これから、そのような場面を掘り下げてみましょう。 + + + -#### 変数とデータの相互作用法: ムーブ +#### ムーブによる変数とデータの相互作用 + リスト4-2: 変数`x`の整数値を`y`に代入する @@ -584,17 +528,16 @@ Now let’s look at the `String` version: では、`String`バージョンを見ていきましょう: ```rust -let s1 = String::from("hello"); -let s2 = s1; +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-03-string-move/src/main.rs:here}} ``` -このコードは先ほどのコードに酷似していますので、動作方法も同じだと思い込んでしまうかもしれません: +このコードは酷似していますので、動作方法も同じだと思い込んでしまうかもしれません: 要するに、2行目で`s1`の値をコピーし、`s2`に束縛するということです。ところが、 これは全く起こることを言い当てていません。 @@ -612,26 +555,34 @@ heap that holds the contents. 右側には、中身を保持したヒープ上のメモリがあります。 -メモリ上の文字列 +2個の表: 1個目の表はスタック上のs1の表現を含み、表はs1の長さ(5)、許容量(5)、
+そして2個目の表の最初の値へのポインタからなる。2個目の表はヒープ上の文字列データのバイト単位の表現を含む。 - + 図4-1: `s1`に束縛された`"hello"`という値を保持する`String`のメモリ上の表現 長さは、`String`型の中身が現在使用しているメモリ量をバイトで表したものです。許容量は、 -`String`型がOSから受け取った全メモリ量をバイトで表したものです。長さと許容量の違いは問題になることですが、 +`String`型がアロケータから受け取った全メモリ量をバイトで表したものです。長さと許容量の違いは問題になることですが、 この文脈では違うので、とりあえずは、許容量を無視しても構わないでしょう。 -同じ値を指すs1とs2 +3個の表: 表s1とs2はスタック上の文字列s1とs2それぞれを表現し、どちらもヒープ上の同じ文字列データを指している。 - + 図4-2: `s1`のポインタ、長さ、許容量のコピーを保持する変数`s2`のメモリ上での表現 @@ -668,13 +624,18 @@ Rustが代わりにヒープデータもコピーするという選択をして ヒープ上のデータが大きい時に`s2 = s1`という処理の実行時性能がとても悪くなっていた可能性があるでしょう。 -2箇所へのs1とs2 +4個の表: 2個の表はs1とs2のスタックデータを表現し、それぞれがヒープ上の文字列データのコピーを指している。 - + 図4-3: Rustがヒープデータもコピーしていた場合に`s2 = s1`という処理が行なった可能性のあること @@ -696,27 +657,18 @@ corruption, which can potentially lead to security vulnerabilities. セキュリティ上の脆弱性を生む可能性があります。 - - -メモリ安全性を保証するために、Rustにおいてこの場面で起こることの詳細がもう一つあります。 -確保されたメモリをコピーしようとする代わりに、コンパイラは、`s1`が最早有効ではないと考え、 +メモリ安全性を保証するために、`let s2 = s1;`の行の後、コンパイラは`s1`が最早有効ではないとみなします。 故に`s1`がスコープを抜けた際に何も解放する必要がなくなるわけです。`s2`の生成後に`s1`を使用しようとしたら、 どうなるかを確認してみましょう。動かないでしょう: -```rust,ignore -let s1 = String::from("hello"); -let s2 = s1; - -println!("{}, world!", s1); +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/src/main.rs:here}} ``` src/main.rs:5:28 - | -3 | let s2 = s1; - | -- value moved here -4 | -5 | println!("{}, world!", s1); - | ^^ value used here after move - | (ムーブ後にここで使用されています) - | - = note: move occurs because `s1` has type `std::string::String`, which does - not implement the `Copy` trait - (注釈: ムーブが起きたのは、`s1`が`std::string::String`という - `Copy`トレイトを実装していない型だからです) +```console +{{#include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt}} ``` -他の言語を触っている間に"shallow copy"と"deep copy"という用語を耳にしたことがあるなら、 -データのコピーなしにポインタと長さ、許容量をコピーするという概念は、shallow copyのように思えるかもしれません。 +他の言語を触っている間に*shallow copy*と*deep copy*という用語を耳にしたことがあるなら、 +データのコピーなしにポインタと長さ、許容量をコピーするという概念は、shallow copyすることのように思えるかもしれません。 ですが、コンパイラは最初の変数をも無効化するので、shallow copyと呼ばれる代わりに、 *ムーブ*として知られているわけです。この例では、`s1`は`s2`に*ムーブ*されたと表現するでしょう。 以上より、実際に起きることを図4-4に示してみました。 -s2にムーブされたs1 +3個の表: 表s1とs2はスタック上の文字列s1とs2それぞれを表現し、どちらもヒープ上の同じ文字列データを指している。
+s1はもう有効ではないので、表s1はグレー表示されている。
+s2だけがヒープデータにアクセスするために使用できる。 - + 図4-4: `s1`が無効化された後のメモリ表現 @@ -788,11 +734,16 @@ copying can be assumed to be inexpensive in terms of runtime performance. 自動的にデータの"deep copy"が行われることは絶対にないわけです。それ故に、あらゆる*自動*コピーは、実行時性能の観点で言うと、 悪くないと考えてよいことになります。 + -#### 変数とデータの相互作用法: クローン + + +#### クローンによる変数とデータの相互作用 まだ話題にしていない別の問題があります。 この整数を使用したコードは、一部をリスト4-2で示しましたが、うまく動作する有効なものです: ```rust -let x = 5; -let y = x; - -println!("x = {}, y = {}", x, y); +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-06-copy/src/main.rs:here}} ``` その理由は、整数のようなコンパイル時に既知のサイズを持つ型は、スタック上にすっぽり保持されるので、 @@ -881,41 +826,51 @@ differently from the usual shallow copying and we can leave it out. Rustには`Copy`トレイトと呼ばれる特別な注釈があり、 -整数のようなスタックに保持される型に対して配置することができます(トレイトについては第10章でもっと詳しく話します)。 -型が`Copy`トレイトに適合していれば、代入後も古い変数が使用可能になります。コンパイラは、 -型やその一部分でも`Drop`トレイトを実装している場合、`Copy`トレイトによる注釈をさせてくれません。 +整数のようなスタックに保持される型に対して配置することができます(トレイトについては[第10章][traits]でもっと詳しく話します)。 +型が`Copy`トレイトを実装していれば、その型を持つ変数はムーブされず、代わりに自明な方法でにコピーされます。 +そのため、他の変数に代入した後でも、元の変数は有効なままです。 + + + +コンパイラは、型やその一部分でも`Drop`トレイトを実装している場合、`Copy`による注釈をさせてくれません。 型の値がスコープを外れた時に何か特別なことを起こす必要がある場合に、`Copy`注釈を追加すると、コンパイルエラーが出ます。 -型に`Copy`注釈をつける方法について学ぶには、付録Cの「導出可能なトレイト」をご覧ください。 +型に`Copy`注釈をつけてトレイトを実装する方法について学ぶには、付録Cの[「導出可能なトレイト」][derivable-traits]をご覧ください。 -では、どの型が`Copy`なのでしょうか?ある型について、ドキュメントをチェックすればいいのですが、 -一般規則として、単純なスカラー値の集合は何でも`Copy`であり、メモリ確保が必要だったり、 -何らかの形態のリソースだったりするものは`Copy`ではありません。ここに`Copy`の型の一部を並べておきます。 +では、どの型が`Copy`トレイトを実装しているのでしょうか? +確実に知るためには、調べたい型のドキュメントをチェックすればいいのですが、 +一般規則として、単純なスカラー値の集合は何でも`Copy`を実装でき、メモリ確保が必要だったり、 +何らかの形態のリソースだったりするものは`Copy`を実装できません。ここに`Copy`を実装する型の一部を並べておきます。 * あらゆる整数型。`u32`など。 @@ -932,13 +887,13 @@ be sure, but as a general rule, any group of simple scalar values can be ### 所有権と関数 -意味論的に、関数に値を渡すことと、値を変数に代入することは似ています。関数に変数を渡すと、 +関数に値を渡すことと、値を変数に代入することの仕組みは似ています。関数に変数を渡すと、 代入のようにムーブやコピーされます。リスト4-3は変数がスコープに入ったり、 抜けたりする地点について注釈してある例です。 @@ -948,75 +903,15 @@ showing where variables go into and out of scope. ファイル名: src/main.rs - - - - - - - - - - - +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-03/src/main.rs}} +``` -```rust -fn main() { - let s = String::from("hello"); // sがスコープに入る - - takes_ownership(s); // sの値が関数にムーブされ... - // ... ここではもう有効ではない - - let x = 5; // xがスコープに入る - - makes_copy(x); // xも関数にムーブされるが、 - // i32はCopyなので、この後にxを使っても - // 大丈夫 - -} // ここでxがスコープを抜け、sもスコープを抜ける。ただし、sの値はムーブされているので、何も特別なことは起こらない。 - // - -fn takes_ownership(some_string: String) { // some_stringがスコープに入る。 - println!("{}", some_string); -} // ここでsome_stringがスコープを抜け、`drop`が呼ばれる。後ろ盾してたメモリが解放される。 - // - -fn makes_copy(some_integer: i32) { // some_integerがスコープに入る - println!("{}", some_integer); -} // ここでsome_integerがスコープを抜ける。何も特別なことはない。 -``` - - - リスト4-3: 所有権とスコープが注釈された関数群 -値を返すことでも、所有権は移動します。リスト4-4は、リスト4-3と似た注釈のついた例です。 +値を返すことでも、所有権は移動します。リスト4-4に値を返す関数の例を、リスト4-3と似た注釈を付けて示します。 - - - - - - - - - - - - - - - -```rust -fn main() { - let s1 = gives_ownership(); // gives_ownershipは、戻り値をs1に - // ムーブする - - let s2 = String::from("hello"); // s2がスコープに入る - - let s3 = takes_and_gives_back(s2); // s2はtakes_and_gives_backにムーブされ - // 戻り値もs3にムーブされる -} // ここで、s3はスコープを抜け、ドロップされる。s2もスコープを抜けるが、ムーブされているので、 - // 何も起きない。s1もスコープを抜け、ドロップされる。 - -fn gives_ownership() -> String { // gives_ownershipは、戻り値を - // 呼び出した関数にムーブする - - let some_string = String::from("hello"); // some_stringがスコープに入る - - some_string // some_stringが返され、呼び出し元関数に - // ムーブされる -} - -// takes_and_gives_backは、Stringを一つ受け取り、返す。 -fn takes_and_gives_back(a_string: String) -> String { // a_stringがスコープに入る。 - - a_string // a_stringが返され、呼び出し元関数にムーブされる -} +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-04/src/main.rs}} ``` +heap goes out of scope, the value will be cleaned up by `drop` unless ownership +of the data has been moved to another variable. 変数の所有権は、毎回同じパターンを辿っています: 別の変数に値を代入すると、ムーブされます。 -ヒープにデータを含む変数がスコープを抜けると、データが別の変数に所有されるようムーブされていない限り、 +ヒープにデータを含む変数がスコープを抜けると、データの所有権が別の変数にムーブされていない限り、 `drop`により片付けられるでしょう。 -所有権を取り、またその所有権を戻す、ということを全ての関数でしていたら、ちょっとめんどくさいですね。 +これでもいいのですが、所有権を取り、またその所有権を戻す、ということを全ての関数でしていたら、ちょっとめんどくさいですね。 関数に値は使わせるものの所有権を取らないようにさせるにはどうするべきでしょうか。 返したいと思うかもしれない関数本体で発生したあらゆるデータとともに、再利用したかったら、渡されたものをまた返さなきゃいけないのは、 非常に煩わしいことです。 -タプルで、複数の値を返すことは可能です。リスト4-5のようにですね。 +Rustでは、タプルを使って複数の値を返すことができます。リスト4-5のようにですね。 - - - - - - - - - ```rust -fn main() { - let s1 = String::from("hello"); - - let (s2, len) = calculate_length(s1); - - //'{}'の長さは、{}です - println!("The length of '{}' is {}.", s2, len); -} - -fn calculate_length(s: String) -> (String, usize) { - let length = s.len(); // len()メソッドは、Stringの長さを返します - - (s, length) -} +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-05/src/main.rs}} ``` でも、これでは、大袈裟すぎますし、ありふれているはずの概念に対して、作業量が多すぎます。 -私たちにとって幸運なことに、Rustにはこの概念に対する機能があり、*参照*と呼ばれます。 +私たちにとって幸運なことに、Rustには所有権を移動することなく値を使うための機能があり、*参照*と呼ばれます。 + + + +[data-types]: ch03-02-data-types.html#データ型 +[ch8]: ch08-02-strings.html +[traits]: ch10-02-traits.html +[derivable-traits]: appendix-03-derivable-traits.html +[method-syntax]: ch05-03-method-syntax.html#メソッド記法 +[paths-module-tree]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html +[drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html#tymethod.drop diff --git a/src/ch04-02-references-and-borrowing.md b/src/ch04-02-references-and-borrowing.md index ddd58b726..04fef7157 100644 --- a/src/ch04-02-references-and-borrowing.md +++ b/src/ch04-02-references-and-borrowing.md @@ -8,16 +8,23 @@ The issue with the tuple code in Listing 4-5 is that we have to return the `String` to the calling function so we can still use the `String` after the call to `calculate_length`, because the `String` was moved into -`calculate_length`. +`calculate_length`. Instead, we can provide a reference to the `String` value. +A *reference* is like a pointer in that it’s an address we can follow to access +the data stored at that address; that data is owned by some other variable. +Unlike a pointer, a reference is guaranteed to point to a valid value of a +particular type for the life of that reference. --> リスト4-5のタプルコードの問題は、`String`型を呼び出し元の関数に戻さないと、`calculate_length`を呼び出した後に、 `String`オブジェクトが使えなくなることであり、これは`String`オブジェクトが`calculate_length`にムーブされてしまうためでした。 +代わりに、`String`値への参照を渡すことができます。 +*参照*はアドレスであり、それを辿ってそのアドレスに置かれているデータにアクセスできるという点で、ポインタと似ています; +データは他の変数によって所有されています。 +ポインタと異なる点としては、参照はその生存期間中を通して、特定の型の有効な値を指していることが保証されています。 ここで、値の所有権をもらう代わりに引数としてオブジェクトへの参照を取る`calculate_length`関数を定義し、 @@ -30,43 +37,30 @@ value: ファイル名: src/main.rs ```rust -fn main() { - let s1 = String::from("hello"); - - let len = calculate_length(&s1); - - // '{}'の長さは、{}です - println!("The length of '{}' is {}.", s1, len); -} - -fn calculate_length(s: &String) -> usize { - s.len() -} +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:all}} ``` まず、変数宣言と関数の戻り値にあったタプルコードは全てなくなったことに気付いてください。 2番目に、`&s1`を`calcuate_length`に渡し、その定義では、`String`型ではなく、`&String`を受け取っていることに注目してください。 +これらのアンド記号が参照を表しており、これのおかげで所有権をもらうことなく値を参照することができるのです。 +図4-5にこの概念を描写します。 - -これらのアンド記号が参照であり、これのおかげで所有権をもらうことなく値を参照することができるのです。 -図4-5はその図解です。 - - -文字列s1を指す&String型のs +3個の表: sの表はs1の表へのポインタのみを含む。
+s1の表はs1のスタックデータを含み、ヒープ上の文字列データを指している。 > 注釈: `&`による参照の逆は、*参照外し*であり、参照外し演算子の`*`で達成できます。 @@ -92,22 +86,17 @@ Let’s take a closer look at the function call here: ここの関数呼び出しについて、もっと詳しく見てみましょう: ```rust -# fn calculate_length(s: &String) -> usize { -# s.len() -# } -let s1 = String::from("hello"); - -let len = calculate_length(&s1); +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:here}} ``` この`&s1`という記法により、`s1`の値を*参照する*参照を生成することができますが、これを所有することはありません。 -所有してないということは、指している値は、参照がスコープを抜けてもドロップされないということです。 +所有してないということは、指している値は、参照が使用されなくなってもドロップされないということです。 - ```rust -fn calculate_length(s: &String) -> usize { // sはStringへの参照 - s.len() -} // ここで、sはスコープ外になる。けど、参照しているものの所有権を持っているわけではないので - // 何も起こらない +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs:here}} ``` -変数`s`が有効なスコープは、あらゆる関数の引数のものと同じですが、所有権はないので、`s`がスコープを抜けても、 -参照が指しているものをドロップすることはありません。関数が実際の値の代わりに参照を引数に取ると、 +変数`s`が有効なスコープは通常の関数の引数のものと同じですが、`s`はそれが指す値に対する所有権を持っていないので、 +`s`が使用されなくなっても指している値をドロップすることはありません。関数が実際の値の代わりに参照を引数に取ると、 所有権をもらわないので、所有権を返す目的で値を返す必要はありません。 -関数の引数に参照を取ることを*借用*と呼びます。現実生活のように、誰かが何かを所有していたら、 -それを借りることができます。用が済んだら、返さなきゃいけないわけです。 +参照を作成することを*借用*と呼びます。現実生活のように、誰かが何かを所有していたら、 +それを借りることができます。用が済んだら、返さないといけません。持っているのとは違うのです。 @@ -168,16 +146,8 @@ Listing 4-6. Spoiler alert: it doesn’t work! ファイル名: src/main.rs -```rust,ignore -fn main() { - let s = String::from("hello"); - - change(&s); -} - -fn change(some_string: &String) { - some_string.push_str(", world"); -} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-06/src/main.rs}} ``` error.rs:8:5 - | -7 | fn change(some_string: &String) { - | ------- use `&mut String` here to make mutable -8 | some_string.push_str(", world"); - | ^^^^^^^^^^^ cannot borrow as mutable +```console +{{#include ../listings/ch04-understanding-ownership/listing-04-06/output.txt}} ``` -### 可変な参照 +### 可変参照 -一捻り加えるだけでリスト4-6のコードのエラーは解決します: +借用された値を変更できるようにするには、代わりに*可変参照*を使うという一捻りを加えるだけでよく、 +これでリスト4-6のコードを修正できます: -始めに、`s`を`mut`に変えなければなりませんでした。そして、`&mut s`で可変な参照を生成し、 -`some_string: &mut String`で可変な参照を受け入れなければなりませんでした。 +まず`s`が`mut`となるように変更します。次に、`change`関数を呼ぶところで`&mut s`によって可変参照を作成し、 +さらに関数シグネチャを、`some_string: &mut String`で可変参照を受け入れるように更新します。 +これにより、`change`関数は借用する値を変更しようとすることがとても明確になります。 -ところが、可変な参照には大きな制約が一つあります: 特定のスコープで、ある特定のデータに対しては、 -一つしか可変な参照を持てないことです。こちらのコードは失敗します: +可変参照には大きな制約が一つあります: ある値への可変参照が存在するなら、その値への参照を他に作ることはできません。 +このコードは`s`への可変参照を2個作成しようとしていますが、これは失敗します: src/main.rs:5:14 - | -4 | let r1 = &mut s; - | ------ first mutable borrow occurs here - | (最初の可変な参照はここ) -5 | let r2 = &mut s; - | ^^^^^^ second mutable borrow occurs here - | (二つ目の可変な参照はここ) -6 | -7 | println!("{}, {}", r1, r2); - | -- first borrow later used here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0499`. -error: could not compile `ownership` - -To learn more, run the command again with --verbose. +```console +{{#include ../listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt}} ``` -この制約は、可変化を許可するものの、それを非常に統制の取れた形で行えます。これは、新たなRustaceanにとっては、 -壁です。なぜなら、多くの言語では、いつでも好きな時に可変化できるからです。 +このエラーによると、一度に`s`を可変として2回以上借用することはできないので、このコードは不正だ、とのことです。 +最初の可変借用は`r1`にあり、`println!`で使用されるまで続かないといけませんが、この可変借用の作成から使用までの間に、 +`r1`と同じデータを借用する別の可変借用を`r2`に作成しようとしました。 +同じデータへの複数の可変参照が同時に存在することを禁止する、という制約は、可変化を許可するものの、 +それを非常に統制の取れた形で行えます。これは、新たなRustaceanにとっては、 +壁です。なぜなら、多くの言語では、いつでも好きな時に可変化できるからです。 この制約がある利点は、コンパイラがコンパイル時にデータ競合を防ぐことができる点です。 -データ競合とは、競合条件と類似していて、これら3つの振る舞いが起きる時に発生します: +データ競合とは、競合状態と類似していて、これら3つの振る舞いが起きる時に発生します: データ競合は未定義の振る舞いを引き起こし、実行時に追いかけようとした時に特定し解決するのが難しい問題です。 -しかし、Rustは、データ競合が起こるコードをコンパイルさえしないので、この問題が発生しないようにしてくれるわけです。 +しかし、Rustは、データ競合が起こるコードのコンパイルを拒否することで、この問題が発生しないようにしてくれるわけです。 +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs:here}} +``` - +コンパイラは可変と不変な参照を組み合わせることに関しても、似たような規則を強制します。このコードはエラーになります: - - -```rust -let mut s = String::from("hello"); -{ - let r1 = &mut s; + -} // r1はここでスコープを抜けるので、問題なく新しい参照を作ることができる +これがエラーです: -let r2 = &mut s; +```console +{{#include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt}} ``` -可変と不変な参照を組み合わせることに関しても、似たような規則が存在しています。このコードはエラーになります: +ふう!*さらに*不変な参照をしている間は、同じ値に対して可変な参照をすることはできません。 - - -```rust,ignore -let mut s = String::from("hello"); - -let r1 = &s; // 問題なし -let r2 = &s; // 問題なし -let r3 = &mut s; // 大問題! -``` +不変参照の使用者は、それ以降に値が突然変わることなんて予想してません! +しかしながら、複数の不変参照をすることは許されています。 +データを読み込んでいるだけの人に、他人がデータを読み込むことに対して影響を与える能力はないからです。 -これがエラーです: +参照のスコープは、それが導入されたところから始まり、その参照が最後に使用される時点まで続きます。 +例えば、次のコードはコンパイルできるでしょう。不変参照の最後の使用箇所である`println!`は、 +可変参照が導入されるよりも前に発生するからです: -```text -error[E0502]: cannot borrow `s` as mutable because it is also borrowed as -immutable -(エラー: `s`は不変で借用されているので、可変で借用できません) - --> borrow_thrice.rs:6:19 - | -4 | let r1 = &s; // no problem - | - immutable borrow occurs here -5 | let r2 = &s; // no problem -6 | let r3 = &mut s; // BIG PROBLEM - | ^ mutable borrow occurs here -7 | } - | - immutable borrow ends here +```rust,edition2021 +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs:here}} ``` -ふう!*さらに*不変な参照をしている間は、可変な参照をすることはできません。不変参照の使用者は、 -それ以降に値が突然変わることなんて予想してません!しかしながら、複数の不変参照をすることは可能です。 -データを読み込んでいるだけの人に、他人がデータを読み込むことに対して影響を与える能力はないからです。 +不変参照`r1`と`r2`のスコープは、それらが最後に使用される`println!`の後で終了します。 +これは可変参照`r3`が作成されるより前のことです。これらのスコープは重なっていないので、 +このコードは許可されます: コンパイラは、スコープの終了より前の時点で参照がもはや使用されていないということを、 +判別できるのです。 -これらのエラーは、時としてイライラするものではありますが、Rustコンパイラがバグの可能性を早期に指摘してくれ(それも実行時ではなくコンパイル時に)、 +借用エラーは、時としてイライラするものではありますが、Rustコンパイラがバグの可能性を早期に指摘してくれ(それも実行時ではなくコンパイル時に)、 問題の発生箇所をズバリ示してくれるのだと覚えておいてください。そうして想定通りにデータが変わらない理由を追いかける必要がなくなります。 -ダングリング参照作りを試してみますが、コンパイラはこれをコンパイルエラーで阻止します: +ダングリング参照を作ってみて、コンパイラがどのようにこれをコンパイルエラーで阻止するか見てみましょう: main.rs:5:16 - | -5 | fn dangle() -> &String { - | ^ expected lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no - value for it to be borrowed from - (助言: この関数の戻り値型は、借用した値を含んでいますが、借用される値がどこにもありません) - = help: consider giving it a 'static lifetime - ('staticライフタイムを与えることを考慮してみてください) +```console +{{#include ../listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt}} ``` -このエラーメッセージは、まだ講義していない機能について触れています: *ライフタイム*です。 +このエラーメッセージは、まだ講義していない機能について触れています: ライフタイムです。 ライフタイムについては第10章で詳しく議論しますが、ライフタイムに関する部分を無視すれば、 このメッセージは、確かにこのコードが問題になる理由に関する鍵を握っています: ```text this function's return type contains a borrowed value, but there is no value -for it to be borrowed from. +for it to be borrowed from ``` - - - - - ファイル名: src/main.rs -```rust,ignore -fn dangle() -> &String { // dangleはStringへの参照を返す - - let s = String::from("hello"); // sは新しいString - - &s // String sへの参照を返す -} // ここで、sはスコープを抜け、ドロップされる。そのメモリは消される。 - // 危険だ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs:here}} ``` diff --git a/src/ch04-03-slices.md b/src/ch04-03-slices.md index e33bc3742..a9a0ed65c 100644 --- a/src/ch04-03-slices.md +++ b/src/ch04-03-slices.md @@ -5,44 +5,46 @@ ## スライス型 -所有権のない別のデータ型は、*スライス*です。スライスにより、コレクション全体ではなく、 -その内の一連の要素を参照することができます。 +*スライス*により、コレクション全体ではなく、その内の連続した要素の列を参照することができます。 +スライスは参照の一種であり、そのため所有権を持っていません。 -ちょっとしたプログラミングの問題を考えてみましょう: 文字列を受け取って、その文字列中の最初の単語を返す関数を書いてください。 +ちょっとしたプログラミングの問題を考えてみましょう: スペースで区切られた複数の単語からなる文字列を受け取って、その文字列中の最初の単語を返す関数を書いてください。 関数が文字列中に空白を見つけられなかったら、文字列全体が一つの単語に違いないので、文字列全体が返されるべきです。 -この関数のシグニチャについて考えてみましょう: +スライスが解決しようとしている問題を理解するために、スライスを使わずにこの関数のシグネチャをどう書くかという問題を通して、 +考えてみましょう。 ```rust,ignore fn first_word(s: &String) -> ? ``` -この関数、`first_word`は引数に`&String`をとります。所有権はいらないので、これで十分です。 +`first_word`関数は引数に`&String`をとります。所有権はいらないので、これで十分です。 ですが、何を返すべきでしょうか?文字列の*一部*について語る方法が全くありません。しかし、 -単語の終端の添え字を返すことができますね。リスト4-7に示したように、その方法を試してみましょう。 +空白によって示される単語の終端の添え字を返すことができますね。リスト4-7に示したように、その方法を試してみましょう。 `String`の値を要素ごとに見て、空白かどうかを確かめる必要があるので、 @@ -85,35 +87,37 @@ Next, we create an iterator over the array of bytes using the `iter` method: ``` -イテレータについて詳しくは、第13章で議論します。今は、`iter`は、コレクション内の各要素を返すメソッドであること、 +イテレータについて詳しくは、[第13章][ch13]で議論します。今は、`iter`は、コレクション内の各要素を返すメソッドであること、 `enumerate`が`iter`の結果をラップして、(結果をそのまま返す)代わりにタプルの一部として各要素を返すことを知っておいてください。 `enumerate`から返ってくるタプルの第1要素は、添え字であり、2番目の要素は、(コレクションの)要素への参照になります。 これは、手動で添え字を計算するよりも少しだけ便利です。 -`enumerate`メソッドがタプルを返すので、Rustのあらゆる場所同様、パターンを使って、そのタプルを分配できます。 -従って、`for`ループ内で、タプルの添え字に対する`i`とタプルの1バイトに対応する`&item`を含むパターンを指定しています。 +`enumerate`メソッドがタプルを返すので、パターンを使って、そのタプルを分配できます。 +パターンについては[第6章][ch6]でさらに議論します。 +`for`ループ内で、タプルの添え字に対する`i`とタプルの1バイトに対応する`&item`を含むパターンを指定しています。 `.iter().enumerate()`から要素への参照を取得するので、パターンに`&`を使っています。 `for`ループ内で、バイトリテラル表記を使用して空白を表すバイトを検索しています。空白が見つかったら、その位置を返します。 @@ -184,8 +188,8 @@ fn second_word(s: &String) -> (usize, usize) { 今、私たちは開始*と*終端の添え字を追うようになりました。特定の状態のデータから計算されたが、 @@ -214,29 +218,23 @@ A *string slice* is a reference to part of a `String`, and it looks like this: ``` -これは、`String`全体への参照を取ることに似ていますが、余計な`[0..5]`という部分が付いています。 -`String`全体への参照ではなく、`String`の一部への参照です。 - - - -`[starting_index..ending_index]`と指定することで、角かっこに範囲を使い、スライスを生成できます。 +`hello`は`String`全体への参照ではなく、追加の`[0..5]`という部分で指定された、`String`の一部への参照です。 +`[starting_index..ending_index]`と指定することで、角かっこに範囲を使い、スライスを生成します。 ここで、`starting_index`はスライスの最初の位置、`ending_index`はスライスの終端位置よりも、 1大きい値です。内部的には、スライスデータ構造は、開始地点とスライスの長さを保持しており、 スライスの長さは`ending_index`から`starting_index`を引いたものに対応します。以上より、 -`let world = &s[6..11];`の場合には、`world`は`s`の添え字6のバイトへのポインタと5という長さを持つスライスになるでしょう。 +`let world = &s[6..11];`の場合には、`world`は`s`の添え字6のバイトへのポインタと`5`という長さを持つスライスになるでしょう。 -文字列sの6バイト目へのポインタと長さ5を保持するworld +3個の表: sのスタックデータを表現するテーブルは、ヒープ上の文字列データ"hello world"のテーブル内の添え字0のバイトを指している。
+3個目の表はスライスworldのスタックデータを表現していて、長さの値5を持ち、ヒープデータの表のバイト6を指している。 -Rustの`..`という範囲記法で、最初の番号(ゼロ)から始めたければ、2連ピリオドの前に値を書かなければいいです。 +Rustの`..`という範囲記法で、添え字0から始めたければ、2連ピリオドの前に値を書かなければいいです。 換言すれば、これらは等価です: ```rust @@ -338,10 +342,10 @@ slice. The type that signifies “string slice” is written as `&str`: ``` リスト4-7で取った方法と同じように、最初の空白を探すことで単語の終端の添え字を取得しています。 @@ -367,7 +371,7 @@ fn second_word(s: &String) -> &str { ``` 借用規則から、何かへの不変な参照がある時、さらに可変な参照を得ることはできないことを思い出してください。 -`clear`は`String`を切り詰める必要があるので、可変な参照を得る必要があります。Rustはこれを認めないので、コンパイルが失敗します。 +`clear`は`String`を切り詰める必要があるので、可変な参照を得る必要があります。 +`clear`の呼び出しの後の`println!`は`word`中の参照を使用するので、不変参照はその時点でもまだ有効でなくてはいけません。 +Rustは`clear`中の可変参照と`word`中の不変参照が同時に存在することを認めないので、コンパイルが失敗します。 RustのおかげでAPIが使いやすくなるだけでなく、ある種のエラー全てを完全にコンパイル時に排除してくれるのです! + + + -#### 文字列リテラルはスライスである +#### スライスとしての文字列リテラル もし、文字列スライスがあるなら、それを直接渡せます。`String`があるなら、 -その`String`全体のスライスを渡せます。`String`への参照の代わりに文字列スライスを取るよう関数を定義すると、 +その`String`のスライスか、`String`への参照を渡せます。この柔軟性は、第15章の[「関数やメソッドで暗黙的な参照外し型強制」][deref-coercions]で扱う機能、 +*参照外し型強制*の利点を活用して実現されています。 + + + +`String`への参照の代わりに文字列スライスを取るよう関数を定義すると、 何も機能を失うことなくAPIをより一般的で有益なものにできるのです。 Filename: src/main.rs @@ -508,7 +531,7 @@ without losing any functionality: 文字列リテラルは、ご想像通り、文字列に特化したものです。ですが、もっと一般的なスライス型も存在します。 @@ -519,8 +542,8 @@ let a = [1, 2, 3, 4, 5]; ``` 文字列の一部を参照したくなる可能性があるのと同様、配列の一部を参照したくなる可能性もあります。 @@ -530,6 +553,8 @@ to part of an array. We’d do so like this: let a = [1, 2, 3, 4, 5]; let slice = &a[1..3]; + +assert_eq!(slice, &[2, 3]); ``` + +[ch13]: ch13-02-iterators.html +[ch6]: ch06-02-match.html#値に束縛されるパターン [strings]: ch08-02-strings.html#文字列でutf-8でエンコードされたテキストを保持する +[deref-coercions]: ch15-02-deref.html#関数やメソッドで暗黙的な参照外し型強制 diff --git a/src/ch05-00-structs.md b/src/ch05-00-structs.md index 28fca40bf..16458e0af 100644 --- a/src/ch05-00-structs.md +++ b/src/ch05-00-structs.md @@ -5,19 +5,26 @@ # 構造体を使用して関係のあるデータを構造化する *struct*または、*構造体*は、意味のあるグループを形成する複数の関連した値をまとめ、名前付けできる独自のデータ型です。 あなたがオブジェクト指向言語に造詣が深いなら、*struct*はオブジェクトのデータ属性みたいなものです。 -この章では、タプルと構造体を対照的に比較し、構造体の使用法をデモし、メソッドや関連関数を定義して、 -構造体のデータに紐付く振る舞いを指定する方法について議論します。構造体と*enum*(第6章で議論します)は、 -自分のプログラム領域で新しい型を定義し、Rustのコンパイル時型精査機能をフル活用する構成要素になります。 +この章では、すでに学習したものに積み重ねる目的でタプルと構造体を対照的に比較し、データをまとめるのに構造体がより良い方法となるのはどういう場合かを示します。 + + + +構造体を定義してインスタンス化する方法を実演します。 +関連関数、特に*メソッド*と呼ばれる種類の関連関数を定義して、構造体型に紐付く振る舞いを指定する方法について議論します。 +構造体と*enum*(第6章で議論します)は、自分のプログラム領域で新しい型を定義し、Rustのコンパイル時型精査機能をフル活用する構成要素になります。 \ No newline at end of file diff --git a/src/ch05-01-defining-structs.md b/src/ch05-01-defining-structs.md index f53841954..ba2a031be 100644 --- a/src/ch05-01-defining-structs.md +++ b/src/ch05-01-defining-structs.md @@ -5,16 +5,18 @@ ## 構造体を定義し、インスタンス化する -構造体は第3章で議論したタプルと似ています。タプル同様、構造体の一部を異なる型にできます。 -一方タプルとは違って、各データ片には名前をつけるので、値の意味が明確になります。 -この名前のおかげで、構造体はタプルに比して、より柔軟になるわけです: データの順番に頼って、 +構造体は、[「タプル型」][tuples]の節で議論したタプルと、どちらも関係する複数の値を抱えるという点で似ています。 +タプル同様、構造体の一部を異なる型にできます。 +一方タプルとは違って、構造体では各データ片には名前をつけるので、値の意味が明確になります。 +これらの名前が付いていることで、構造体はタプルに比して、より柔軟になるわけです: データの順番に頼って、 インスタンスの値を指定したり、アクセスしたりする必要がないのです。 + +ファイル名: src/main.rs + ```rust -struct User { - username: String, - email: String, - sign_in_count: u64, - active: bool, -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs:here}} ``` 構造体を定義した後に使用するには、各フィールドに対して具体的な値を指定して構造体の*インスタンス*を生成します。 -インスタンスは、構造体名を記述し、`key: value`ペアを含む波かっこを付け加えることで生成します。 +インスタンスは、構造体名を記述し、*key: value*ペアを含む波かっこを付け加えることで生成します。 ここで、キーはフィールド名、値はそのフィールドに格納したいデータになります。フィールドは、 構造体で宣言した通りの順番に指定する必要はありません。換言すると、構造体定義とは、 型に対する一般的な雛形のようなものであり、インスタンスは、その雛形を特定のデータで埋め、その型の値を生成するわけです。 例えば、リスト5-2で示されたように特定のユーザを宣言することができます。 + + +ファイル名: src/main.rs + ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -let user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), - active: true, - sign_in_count: 1, -}; +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs:here}} ``` -構造体から特定の値を得るには、ドット記法が使えます。このユーザのEメールアドレスだけが欲しいなら、 -この値を使いたかった場所全部で`user1.email`が使えます。インスタンスが可変であれば、 -ドット記法を使い特定のフィールドに代入することで値を変更できます。リスト5-3では、 -可変な`User`インスタンスの`email`フィールド値を変更する方法を示しています。 +構造体から特定の値を得るには、ドット記法を使います。例えば、 +このユーザのEメールアドレスにアクセスするには、`user1.email`を使います。 +インスタンスが可変であれば、ドット記法を使い特定のフィールドに代入することで値を変更できます。 +リスト5-3では、可変な`User`インスタンスの`email`フィールド値を変更する方法を示しています。 + + + +ファイル名: src/main.rs ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -let mut user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), - active: true, - sign_in_count: 1, -}; - -user1.email = String::from("anotheremail@example.com"); +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs:here}} ``` + +ファイル名: src/main.rs + ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -fn build_user(email: String, username: String) -> User { - User { - email: email, - username: username, - active: true, - sign_in_count: 1, - } -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs:here}} ``` 構造体のフィールドと同じ名前を関数の引数にもつけることは筋が通っていますが、 @@ -182,47 +163,44 @@ would get even more annoying. Luckily, there's a convenient shorthand! 構造体にもっとフィールドがあれば、名前を繰り返すことはさらに煩わしくなるでしょう。 幸運なことに、便利な省略記法があります! + -### フィールドと変数が同名の時にフィールド初期化省略記法を使う + + +### フィールド初期化省略記法を使う 仮引数名と構造体のフィールド名がリスト5-4では、全く一緒なので、*フィールド初期化省略*記法を使って`build_user`を書き換えても、 -振る舞いは全く同じにしつつ、リスト5-5に示したように`email`と`username`を繰り返さなくてもよくなります。 +振る舞いは全く同じにしつつ、リスト5-5に示したように`username`と`email`を繰り返さなくてもよくなります。 + + + +ファイル名: src/main.rs ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -fn build_user(email: String, username: String) -> User { - User { - email, - username, - active: true, - sign_in_count: 1, - } -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs:here}} ``` -リスト5-5: `email`と`username`引数が構造体のフィールドと同名なので、 +リスト5-5: `username`と`email`引数が構造体のフィールドと同名なので、 フィールド初期化省略法を使用する`build_user`関数 ### 構造体更新記法で他のインスタンスからインスタンスを生成する -多くは前のインスタンスの値を使用しつつ、変更する箇所もある形で新しいインスタンスを生成できるとしばしば有用です。 +他のインスタンスからの値の多くの部分を含みつつ、一部を変更する形で新しいインスタンスを生成できるとしばしば有用です。 *構造体更新記法*でそうすることができます。 -まず、リスト5-6では、更新記法なしで`user2`に新しい`User`インスタンスを生成する方法を示しています。 -`email`と`username`には新しい値をセットしていますが、それ以外にはリスト5-2で生成した`user1`の値を使用しています。 +まず、リスト5-6では、更新記法なしで普通に`user2`に新しい`User`インスタンスを生成する方法を示しています。 +`email`には新しい値をセットしていますが、それ以外にはリスト5-2で生成した`user1`の値を使用しています。 + + + +ファイル名: src/main.rs ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -# let user1 = User { -# email: String::from("someone@example.com"), -# username: String::from("someusername123"), -# active: true, -# sign_in_count: 1, -# }; -# -let user2 = User { - email: String::from("another@example.com"), - username: String::from("anotherusername567"), - active: user1.active, - sign_in_count: user1.sign_in_count, -}; +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs:here}} ``` リスト5-6: `user1`の一部の値を使用しつつ、新しい`User`インスタンスを生成する @@ -300,203 +266,275 @@ explicitly set should have the same value as the fields in the given instance. 構造体更新記法を使用すると、リスト5-7に示したように、コード量を減らしつつ、同じ効果を達成できます。`..`という記法により、 明示的にセットされていない残りのフィールドが、与えられたインスタンスのフィールドと同じ値になるように指定します。 + + +ファイル名: src/main.rs + ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -# let user1 = User { -# email: String::from("someone@example.com"), -# username: String::from("someusername123"), -# active: true, -# sign_in_count: 1, -# }; -# -let user2 = User { - email: String::from("another@example.com"), - username: String::from("anotherusername567"), - ..user1 -}; +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs:here}} ``` -リスト5-7: 構造体更新記法を使用して、新しい`User`インスタンス用の値に新しい`email`と`username`をセットしつつ、 -残りの値は、`user1`変数のフィールド値を使う +リスト5-7: 構造体更新記法を使用して、新しい`User`インスタンス用の値に新しい`email`をセットしつつ、 +残りの値は`user1`を使う -リスト5-7のコードも、`email`と`username`については異なる値、`active`と`sign_in_count`フィールドについては、 +リスト5-7のコードも、`email`については`user1`とは異なる値、`username`、`active`と`sign_in_count`フィールドについては、 `user1`と同じ値になるインスタンスを`user2`に生成します。 +`..user1`は、残りのフィールドについては`user1`の対応するフィールドから値を取る、ということを示すために最後に来る必要がありますが、 +フィールドについては好きなだけ多く、構造体定義中のフィールドの順序とは無関係に好きな順で、値を指定してかまいません。 + + + +構造体更新記法は代入と同様に`=`を使います; これは、[「ムーブによる変数とデータの相互作用」][move]の節で見たのと同じように、 +データをムーブするからです。この例で言うと、`user2`を作成した後は、もう`user1`をそっくりそのまま使うことはできません。 +`user1`の`username`フィールド中の`String`が`user2`の中にムーブされてしまったからです。 +もし`user2`に、`email`と`username`のために新しい`String`値を与えていたなら、つまり、 +`user1`からは`active`と`sign_in_count`の値だけを使用していたなら、`user2`を作成した後も`user1`はまだ有効だったでしょう。 +`active`と`sign_in_count`はどちらも`Copy`トレイトを実装した型なので、[「スタックのみのデータ: コピー」][copy]節で議論した振る舞いが適用されるからです。 ### 異なる型を生成する名前付きフィールドのないタプル構造体を使用する -構造体名により追加の意味を含むものの、フィールドに紐づけられた名前がなく、むしろフィールドの型だけの*タプル構造体*と呼ばれる、 -タプルに似た構造体を定義することもできます。タプル構造体は、構造体名が提供する追加の意味は含むものの、 +Rustは、構造体名により追加の意味を含むものの、フィールドに紐づけられた名前がなく、むしろフィールドの型だけの*タプル構造体*と呼ばれる、 +タプルに似た構造体もサポートしています。タプル構造体は、構造体名が提供する追加の意味は含むものの、 フィールドに紐付けられた名前はありません; むしろ、フィールドの型だけが存在します。タプル構造体は、タプル全体に名前をつけ、 -そのタプルを他のタプルとは異なる型にしたい場合に有用ですが、普通の構造体のように各フィールド名を与えるのは、 -冗長、または余計になるでしょう。 +そのタプルを他のタプルとは異なる型にしたいが、普通の構造体のように各フィールド名を与えるのは、 +冗長、または余計という場合に有用です。 -タプル構造体を定義するには、`struct`キーワードの後に構造体名、さらにタプルに含まれる型を続けます。 -例えば、こちらは、`Color`と`Point`という2種類のタプル構造体の定義と使用法です: +タプル構造体を定義するには、`struct`キーワードの後に構造体名、さらにタプルに含まれる型を続けてください。 +例えば、ここでは、`Color`と`Point`という2種類のタプル構造体の定義して使用します: -```rust -struct Color(i32, i32, i32); -struct Point(i32, i32, i32); + + +ファイル名: src/main.rs -let black = Color(0, 0, 0); -let origin = Point(0, 0, 0); +```rust +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs}} ``` `black`と`origin`の値は、違う型であることに注目してください。これらは、異なるタプル構造体のインスタンスだからですね。 定義された各構造体は、構造体内のフィールドが同じ型であっても、それ自身が独自の型になります。 例えば、`Color`型を引数に取る関数は、`Point`を引数に取ることはできません。たとえ、両者の型が、 3つの`i32`値からできていてもです。それ以外については、タプル構造体のインスタンスは、 -タプルと同じように振る舞います: 分配して個々の部品にしたり、`.`と添え字を使用して個々の値にアクセスするなどです。 +分配して個々の部品にしたり、`.`と添え字を使用して個々の値にアクセスできるという点で、タプルと似ています。 ### フィールドのないユニット(よう)構造体 -また、一切フィールドのない構造体を定義することもできます!これらは、`()`、ユニット型と似たような振る舞いをすることから、 +また、一切フィールドのない構造体を定義することもできます!これらは、`()`、 +[「タプル型」][tuples]の節で言及したユニット型と似たような振る舞いをすることから、 *ユニット様構造体*と呼ばれます。ユニット様構造体は、ある型にトレイトを実装するけれども、 型自体に保持させるデータは一切ない場面に有効になります。トレイトについては第10章で議論します。 +以下は、`AlwaysEqual`という名前のユニット様構造体を宣言し、インスタンス化する例です: - -error[E0106]: missing lifetime specifier +`AlwaysEqual`を定義するためには、`struct`キーワード、付けたい名前、そしてセミコロンを使います。 +波括弧や丸括弧は不要です! +次に、同じようにして、`subject`変数に`AlwaysEqual`のインスタンスを得られます: 波括弧や丸括弧を付けずに、定義した名前を使います。 +後でこの型の振る舞いを、おそらくはテスト目的で既知の結果を得るために、`AlwaysEqual`のすべてのインスタンスが常に他の任意の型と等価であるように実装することを想像してください。 +この挙動を実装するためにデータはまったく必要ないですね! +トレイトを定義して、ユニット様構造体も含めた任意の型にそれを実装する方法については10章で触れます。 -| -3 | email: &str, -| ^ expected lifetime parameter -``` + -In Chapter 10, we’ll discuss how to fix these errors so you can store -references in structs, but for now, we’ll fix errors like these using owned -types like `String` instead of references like `&str`. + > ### 構造体データの所有権 > > リスト5-1の`User`構造体定義において、`&str`文字列スライス型ではなく、所有権のある`String`型を使用しました。 -> これは意図的な選択です。というのも、この構造体のインスタンスには全データを所有してもらう必要があり、 +> これは意図的な選択です。というのも、この構造体の各インスタンスには自身の全データを所有してもらう必要があり、 > このデータは、構造体全体が有効な間はずっと有効である必要があるのです。 > > 構造体に、他の何かに所有されたデータへの参照を保持させることもできますが、 > そうするには*ライフタイム*という第10章で議論するRustの機能を使用しなければなりません。 > ライフタイムのおかげで構造体に参照されたデータが、構造体自体が有効な間、ずっと有効であることを保証してくれるのです。 -> ライフタイムを指定せずに構造体に参照を保持させようとしたとしましょう。以下の通りですが、これは動きません: +> 次のように、ライフタイムを指定せずに構造体に参照を保持させようとしたとしましょう。これは動きません: > > ファイル名: src/main.rs > -> ```rust,ignore +> ```rust,ignore,does_not_compile > struct User { +> active: bool, > username: &str, > email: &str, > sign_in_count: u64, -> active: bool, > } > > fn main() { > let user1 = User { -> email: "someone@example.com", -> username: "someusername123", > active: true, +> username: "someusername123", +> email: "someone@example.com", > sign_in_count: 1, > }; > } @@ -504,21 +542,58 @@ types like `String` instead of references like `&str`. > > コンパイラは、ライフタイム指定子が必要だと怒るでしょう: > -> ```text +> ```console +> $ cargo run +> Compiling structs v0.1.0 (file:///projects/structs) > error[E0106]: missing lifetime specifier > (エラー: ライフタイム指定子がありません) -> --> -> | -> 2 | username: &str, -> | ^ expected lifetime parameter -> (ライフタイム引数を予期しました) +> --> src/main.rs:3:15 +> | +> 3 | username: &str, +> | ^ expected named lifetime parameter +> | (ライフタイム引数を予期しました) +> | +> help: consider introducing a named lifetime parameter +> | +> 1 ~ struct User<'a> { +> 2 | active: bool, +> 3 ~ username: &'a str, +> | > > error[E0106]: missing lifetime specifier -> --> -> | -> 3 | email: &str, -> | ^ expected lifetime parameter +> --> src/main.rs:4:12 +> | +> 4 | email: &str, +> | ^ expected named lifetime parameter +> | +> help: consider introducing a named lifetime parameter +> | +> 1 ~ struct User<'a> { +> 2 | active: bool, +> 3 | username: &str, +> 4 ~ email: &'a str, +> | +> +> For more information about this error, try `rustc --explain E0106`. +> error: could not compile `structs` (bin "structs") due to 2 previous errors > ``` > > 第10章で、これらのエラーを解消して構造体に参照を保持する方法について議論しますが、 > 当面、今回のようなエラーは、`&str`のような参照の代わりに、`String`のような所有された型を使うことで修正します。 + + + + + +[tuples]: ch03-02-data-types.html#タプル型 +[move]: ch04-01-what-is-ownership.html#ムーブによる変数とデータの相互作用 +[copy]: ch04-01-what-is-ownership.html#スタックのみのデータ-コピー diff --git a/src/ch05-02-example-structs.md b/src/ch05-02-example-structs.md index 76cb30c15..cb2e7151f 100644 --- a/src/ch05-02-example-structs.md +++ b/src/ch05-02-example-structs.md @@ -6,8 +6,8 @@ 構造体を使用したくなる可能性のあるケースを理解するために、長方形の面積を求めるプログラムを書きましょう。 @@ -15,7 +15,7 @@ refactor the program until we’re using structs instead. @@ -31,20 +31,7 @@ Cargoで*rectangles*という新規バイナリプロジェクトを作成しま ファイル名: src/main.rs ```rust -fn main() { - let width1 = 30; - let height1 = 50; - - println!( - // 長方形の面積は、{}平方ピクセルです - "The area of the rectangle is {} square pixels.", - area(width1, height1) - ); -} - -fn area(width: u32, height: u32) -> u32 { - width * height -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs:all}} ``` - -### タプルでリファクタリングする - - -リスト5-8のコードはうまく動き、各寸法を与えて`area`関数を呼び出すことで長方形の面積を割り出しますが、 -改善点があります。幅と高さは、組み合わせると一つの長方形を表すので、相互に関係があるわけです。 +このコードは、各寸法を与えて`area`関数を呼び出すことで長方形の面積を割り出すことができますが、 +このコードはもっと簡潔で読みやすくすることができます。 -`area`関数は、1長方形の面積を求めるものと考えられますが、今書いた関数には、引数が2つあります。 -引数は関連性があるのに、このプログラム内のどこにもそのことは表現されていません。 +`area`関数は、1長方形の面積を求めるものと考えられますが、今書いた関数には引数が2つあり、 +そしてこのプログラム内のどこを見ても、これらの引数に関連性があることが明確になっていません。 幅と高さを一緒にグループ化する方が、より読みやすく、扱いやすくなるでしょう。 -それをする一つの方法については、第3章の「タプル型」節ですでに議論しました: タプルを使うのです。 +それをする一つの方法については、第3章の[「タプル型」][the-tuple-type]節ですでに議論しました: タプルを使うのです。 ある意味では、このプログラムはマシです。タプルのおかげで少し構造的になり、一引数を渡すだけになりました。 しかし別の意味では、このバージョンは明確性を失っています: タプルは要素に名前を付けないので、 -計算が不明瞭になったのです。なぜなら、タプルの一部に添え字アクセスする必要があるからです。 +タプルの要素に添え字でアクセスする必要があり、計算が不明瞭になったのです。 -面積計算で幅と高さを混在させるのなら問題はないのですが、長方形を画面に描画したいとなると、問題になるのです! +面積計算では幅と高さを混同しても問題ないですが、長方形を画面に描画したいとなると、これは問題になります! タプルの添え字`0`が`幅`で、添え字`1`が`高さ`であることを肝に銘じておかなければなりません。 -他人がこのコードをいじることになったら、このことを割り出し、同様に肝に銘じなければならないでしょう。 -容易く、このことを忘れたり、これらの値を混ぜこぜにしたりしてエラーを発生させてしまうでしょう。 -データの意味をコードに載せていないからです。 +もし他人がこのコードを使用することになったら、彼らがこのことを見つけ出して肝に銘じておくのはより難しくなるでしょう。 +データの意味をコードに載せていないことで、エラーを招きやすくなってしまいました。 -データのラベル付けで意味を付与するために構造体を使います。現在使用しているタプルを全体と一部に名前のあるデータ型に、 +データのラベル付けで意味を付与するために構造体を使います。現在使用しているタプルを全体と一部に名前のある構造体に、 変形することができます。そう、リスト5-10に示したように。 ここでは、構造体を定義し、`Rectangle`という名前にしています。波括弧の中で`width`と`height`というフィールドを定義し、 `u32`という型にしました。それから`main`内で`Rectangle`の特定のインスタンスを生成し、 -幅を30、高さを50にしました。 +幅を`30`、高さを`50`にしました。 `area`関数は、`Rectangle`インスタンスの`width`と`height`フィールドにアクセスしています。 +(借用された構造体インスタンスのフィールドにアクセスしても、そのフィールドの値はムーブされないことに注意してください。 +構造体の借用をよく使うのはこのためです) これで、`area`の関数シグニチャは、我々の意図をズバリ示すようになりました: `width`と`height`フィールドを使って、 `Rectangle`の面積を計算します。これにより、幅と高さが相互に関係していることが伝わり、 タプルの`0`や`1`という添え字を使うよりも、これらの値に説明的な名前を与えられるのです。プログラムの意図が明瞭になりました。 @@ -263,14 +218,15 @@ and `1`. This is a win for clarity. ### トレイトの導出で有用な機能を追加する -プログラムのデバッグをしている間に、`Rectangle`のインスタンスを出力し、フィールドの値を確認できると、 -素晴らしいわけです。リスト5-11では、以前の章のように、`println!`マクロを試しに使用しようとしていますが、動きません。 +プログラムのデバッグをしている間に、`Rectangle`のインスタンスを出力し、フィールドの値を確認できると便利でしょう。 +リスト5-11では、以前の章のように、[`println!`マクロ][println]を試しに使用しようとしています。 +ですが、これは動きません。 -このコードを走らせると、こんな感じのエラーが出ます: +このコードをコンパイルすると、こんな感じのエラーが出ます: + + ```text -error[E0277]: the trait bound `Rectangle: std::fmt::Display` is not satisfied -(エラー: トレイト境界`Rectangle: std::fmt::Display`が満たされていません) +{{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt:3:4}} ``` `println!`マクロには、様々な整形があり、標準では、波括弧は`Display`として知られる整形をするよう、 @@ -328,7 +275,7 @@ implementation of `Display`. 標準で`Display`を実装しています。というのも、`1`や他の基本型をユーザに見せる方法は一つしかないからです。 しかし構造体では、`println!`が出力を整形する方法は自明ではなくなります。出力方法がいくつもあるからです: カンマは必要なの?波かっこを出力する必要はある?全フィールドが見えるべき?この曖昧性のため、 -Rustは必要なものを推測しようとせず、構造体には`Display`実装が提供されないのです。 +Rustは必要なものを推測しようとせず、構造体は`println!`と`{}`プレースホルダで使用される`Display`実装を提供しないのです。 + ```text -`Rectangle` cannot be formatted with the default formatter; try using -`:?` instead if you are using a format string -(注釈: `Rectangle`は、デフォルト整形機では、整形できません; フォーマット文字列を使うのなら -代わりに`:?`を試してみてください) +{{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt:10:13}} ``` -変更してコードを走らせてください。なに!まだエラーが出ます: +変更してコードをコンパイルしてください。なに!まだエラーが出ます: + + ```text -error[E0277]: the trait bound `Rectangle: std::fmt::Debug` is not satisfied -(エラー: トレイト境界`Rectangle: std::fmt::Debug`が満たされていません) +{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt:3:4}} ``` + ```text -`Rectangle` cannot be formatted using `:?`; if it is defined in your -crate, add `#[derive(Debug)]` or manually implement it -(注釈: `Rectangle`は`:?`を使って整形できません; 自分のクレートで定義しているのなら -`#[derive(Debug)]`を追加するか、手動で実装してください) +{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt:10:13}} ``` *確かに*Rustにはデバッグ用の情報を出力する機能が備わっていますが、この機能を構造体で使えるようにするには、 -明示的な選択をしなければならないのです。そうするには、構造体定義の直前に`#[derive(Debug)]`という注釈を追加します。 +明示的な選択をしなければならないのです。そうするには、構造体定義の直前に`#[derive(Debug)]`という外部属性を追加します。 そう、リスト5-12で示されている通りです。 -リスト5-12: `Debug`トレイトを導出する注釈を追加し、 +リスト5-12: `Debug`トレイトを導出する属性を追加し、 `Rectangle`インスタンスをデバッグ用整形機で出力する 素晴らしい!最善の出力ではないものの、このインスタンスの全フィールドの値を出力しているので、 @@ -443,33 +379,116 @@ When we use the `{:#?}` style in the example, the output will look like this: そのような場合には、`println!`文字列中の`{:?}`の代わりに`{:#?}`を使うことができます。 この例で`{:#?}`というスタイルを使用したら、出力は以下のようになるでしょう: -```text -rect1 is Rectangle { - width: 30, - height: 50 -} +```console +{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt}} ``` -Rustには、`derive`注釈で使えるトレイトが多く提供されており、独自の型に有用な振る舞いを追加することができます。 +`Debug`整形を使用して値を出力するためのもう一つの方法は、[`dbg!`マクロ][dbg]を使用することです。 +`dbg!`マクロは式の所有権を奪い(参照を取る`println!`とは対照的です)、その呼び出しが発生したコード内のファイル名と行番号とともに式を評価した結果を出力して、 +その値の所有権を返します。 + + + +> 注釈: 標準出力コンソールストリーム(`stdout`)に出力する`println!`とは異なり、`dbg!`マクロの呼び出しは標準エラーコンソールストリーム(`stderr`)に出力します。 +> `stderr`と`stdout`については[12章の「標準出力ではなく標準エラーにエラーメッセージを書き込む」節][err]でより詳しく触れます。 + + + +以下は、`width`フィールドに代入される値と、`rect1`の構造体全体の値に関心がある場合の例です: + +```rust +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs}} +``` + + + +`dbg!`は式が評価された値の所有権を返すため、式`30 * scale`を囲うように`dbg!`を書くことで、`width`フィールドはここで`dbg!`の呼び出しをしなかった場合とまったく同じ値になります。 +`rect1`の所有権は奪ってほしくないので、次の`dbg!`呼び出しでは`rect1`への参照を使用しています。 +この例の出力は以下のようになります: + +```console +{{#include ../listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt}} +``` + + + +出力の前半は*src/main.rs*の10行目からの出力です。 +ここでは式`30 * scale`をデバッグ出力していて、その結果の値は`60`です(整数に実装されている`Debug`整形を使用して出力されています)。 +*src/main.rs*の14行目の`dbg!`呼び出しは`&rect1`の値を出力し、これは`Rectangle`構造体です。 +この出力は `Rectangle`型の pretty `Debug`整形を使用します。 +`dbg!`マクロは、コードが何をしているのか理解しようとするときには非常に有用です! + + + +`Debug`トレイトの他にも、Rustでは`derive`属性で使えるトレイトが多く提供されており、独自の型に有用な振る舞いを追加することができます。 そのようなトレイトとその振る舞いは、付録Cで一覧になっています。 これらのトレイトを独自の動作とともに実装する方法だけでなく、独自のトレイトを生成する方法については、第10章で解説します。 +また、`derive`の他にも多数の属性が存在します; さらなる情報については[Rust Referenceの“Attributes”節][attributes]を参照してください。 `area`関数は、非常に特殊です: 長方形の面積を算出するだけです。`Rectangle`構造体とこの動作をより緊密に結び付けられると、 役に立つでしょう。なぜなら、他のどんな型でもうまく動作しなくなるからです。 `area`関数を`Rectangle`型に定義された`area`*メソッド*に変形することで、 このコードをリファクタリングし続けられる方法について見ていきましょう。 + + + +[the-tuple-type]: ch03-02-data-types.html#タプル型 +[app-c]: appendix-03-derivable-traits.md +[println]: https://doc.rust-lang.org/std/macro.println.html +[dbg]: https://doc.rust-lang.org/std/macro.dbg.html +[err]: ch12-06-writing-to-stderr-instead-of-stdout.html +[attributes]: https://doc.rust-lang.org/reference/attributes.html diff --git a/src/ch05-03-method-syntax.md b/src/ch05-03-method-syntax.md index 9807a8656..5696d5243 100644 --- a/src/ch05-03-method-syntax.md +++ b/src/ch05-03-method-syntax.md @@ -5,19 +5,21 @@ ## メソッド記法 -*メソッド*は関数に似ています: `fn`キーワードと名前で宣言されるし、引数と返り値があるし、 -どこか別の場所で呼び出された時に実行されるコードを含みます。ところが、 -メソッドは構造体の文脈(あるいはenumかトレイトオブジェクトの。これらについては各々第6章と17章で解説します)で定義されるという点で、 -関数とは異なり、最初の引数は必ず`self`になり、これはメソッドが呼び出されている構造体インスタンスを表します。 +*メソッド*は関数に似ています: `fn`キーワードと名前を使って宣言され、引数と戻り値を持つことができ、 +メソッドがどこか別の場所で呼び出された時に実行されるコードを含みます。 +関数とは異なり、メソッドは構造体の文脈の中で定義されます(enumの文脈やトレイトオブジェクトの文脈の中でも定義されますが、これらについてはそれぞれ[6章][enums]と[17章][trait-objects]で解説します)。 +最初の引数は必ず`self`になり、これはメソッドが呼び出されている構造体インスタンスを表します。 - -`Rectangle`の文脈内で関数を定義するには、`impl`(implementation; 実装)ブロックを始めます。 +(implementation) block for `Rectangle`. Everything within this `impl` block +will be associated with the `Rectangle` type. Then we move the `area` function +within the `impl` curly brackets and change the first (and in this case, only) +parameter to be `self` in the signature and everywhere within the body. In +`main`, where we called the `area` function and passed `rect1` as an argument, +we can instead use *method syntax* to call the `area` method on our `Rectangle` +instance. The method syntax goes after an instance: we add a dot followed by +the method name, parentheses, and any arguments. +--> + +`Rectangle`の文脈内で関数を定義するには、`Rectangle`のための`impl`(implementation; 実装)ブロックを始めます。 +この`impl`ブロック内のあらゆる定義は`Rectangle`に関連付けられたものとなるでしょう。 それから`area`関数を`impl`の波かっこ内に移動させ、最初の(今回は唯一の)引数をシグニチャ内と本体内全てで`self`に変えます。 `area`関数を呼び出し、`rect1`を引数として渡す`main`では、代替としてメソッド記法を使用して、 `Rectangle`インスタンスの`area`メソッドを呼び出せます。メソッド記法は、インスタンスの後に続きます: ドット、メソッド名、かっこ、そして引数と続くわけです。 `area`のシグニチャでは、`rectangle: &Rectangle`の代わりに`&self`を使用しています。 -というのも、コンパイラは、このメソッドが`impl Rectangle`という文脈内に存在するために、 -`self`の型が`Rectangle`であると把握しているからです。`&Rectangle`と同様に、 -`self`の直前に`&`を使用していることに注意してください。メソッドは、`self`の所有権を奪ったり、 -ここでしているように不変で`self`を借用したり、可変で`self`を借用したりできるのです。 +`&self`は実際のところ`self: &Self`の省略記法です。 +`impl`ブロック内では、型`Self`はその`impl`ブロックの対象である型に対するエイリアスとして使えます。 +メソッドはその第1引数として`self`という名前の`Self`型引数を持たなくてはならないので、 +Rust処理系は第1引数の位置では`self`という名前のみに省略することを許可しているのです。 +ただし、`self`省略記法の前の`&`は依然として必要であることに注意してください。 +これは、`rectangle: &Rectangle`と書いたときと同様に、このメソッドが`Self`のインスタンスを借用することを示しています。 +メソッドは、`self`の所有権を奪ったり、ここでしているように不変で`self`を借用したり、可変で`self`を借用したりできるのです。 他の引数と全く同じですね。 ここで`&self`を選んでいるのは、関数バージョンで`&Rectangle`を使用していたのと同様の理由です: @@ -121,66 +113,118 @@ to prevent the caller from using the original instance after the transformation. メソッドが`self`を何か別のものに変形し、変形後に呼び出し元が元のインスタンスを使用できないようにしたい場合に使用されます。 -関数の代替としてメソッドを使う主な利点は、メソッド記法を使用して全メソッドのシグニチャで`self`の型を繰り返す必要がなくなる以外だと、 -体系化です。コードの将来的な利用者に`Rectangle`の機能を提供しているライブラリ内の各所でその機能を探させるのではなく、 +関数の代替としてメソッドを使う主な理由は、メソッド記法を使用できるようにすることと、 +すべてのメソッドのシグニチャでいちいち`self`の型を繰り返す必要がなくなることに加えて、体系化のためです。 +コードの将来的な利用者に、私たちが提供するライブラリ内のあらゆる箇所から`Rectangle`の機能を探させるのではなく、 この型のインスタンスでできることを一つの`impl`ブロックにまとめあげています。 - -Here’s how it works: when you call a method with `object.something()`, Rust -automatically adds in `&`, `&mut`, or `*` so `object` matches the signature of -the method. In other words, the following are the same: +ファイル名: src/main.rs ```rust -# #[derive(Debug,Copy,Clone)] -# struct Point { -# x: f64, -# y: f64, -# } -# -# impl Point { -# fn distance(&self, other: &Point) -> f64 { -# let x_squared = f64::powi(other.x - self.x, 2); -# let y_squared = f64::powi(other.y - self.y, 2); -# -# f64::sqrt(x_squared + y_squared) -# } -# } -# let p1 = Point { x: 0.0, y: 0.0 }; -# let p2 = Point { x: 5.0, y: 6.5 }; -p1.distance(&p2); -(&p1).distance(&p2); +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs:here}} ``` -The first one looks much cleaner. This automatic referencing behavior works -because methods have a clear receiver—the type of `self`. Given the receiver -and name of a method, Rust can figure out definitively whether the method is -reading (`&self`), mutating (`&mut self`), or consuming (`self`). The fact -that Rust makes borrowing implicit for method receivers is a big part of -making ownership ergonomic in practice. + + +ここで`width`メソッドは、インスタンスの`width`フィールドの値が`0`より大きい場合に`true`を返し、値が`0`の場合は`false`を返すようにしています: +同名のメソッド内でも、フィールドをあらゆる目的のために使用することができます。 +`main`では`rect1.width`の後に丸かっこを続けているので、処理系はメソッドの`width`を意図したものと認識します。 +丸かっこを使わなければ、処理系はフィールドの`width`を意図したものと認識します。 + + + +フィールドの値を返すだけで他に何もしないメソッドに、フィールドと同じ名前を与えることが、常にではありませんが、よくあります。 +このようなメソッドは*ゲッター*と呼ばれます。 +他のいくつかの言語で行われているような自動的なゲッターの実装を、Rustが構造体フィールドに対して行うことはありません。 +フィールドを非公開にしながらメソッドは公開するということができ、そうすることで、型の公開APIの一部としてフィールドへの読み込み専用アクセスを提供できるので、ゲッターは有用です。 +公開と非公開とはなにか、そしてフィールドやメソッドを公開または非公開として指定する方法については、[7章][public]で議論します。 + + + + > ### `->`演算子はどこに行ったの? @@ -198,6 +242,7 @@ making ownership ergonomic in practice. > コンパイラは`object`がメソッドのシグニチャと合致するように、自動で`&`か`&mut`、`*`を付与するのです。 > 要するに、以下のコードは同じものです: > +> > ```rust > # #[derive(Debug,Copy,Clone)] > # struct Point { @@ -232,17 +277,16 @@ making ownership ergonomic in practice. -`Rectangle`構造体に2番目のメソッドを実装して、メソッドを使う鍛錬をしましょう。今回は、`Rectangle`のインスタンスに、 -別の`Rectangle`のインスタンスを取らせ、2番目の`Rectangle`が`self`に完全にはめ込まれたら、`true`を返すようにしたいのです; -そうでなければ、`false`を返すべきです。つまり、一旦`can_hold`メソッドを定義したら、 -リスト5-14のようなプログラムを書けるようになりたいのです。 +`Rectangle`構造体に2番目のメソッドを実装して、メソッドを使う練習をしましょう。 +今回は`Rectangle`のインスタンスに別の`Rectangle`のインスタンスを受け取らせ、2番目の`Rectangle`が`self`(1番目の`Rectangle`)に完全に収まるなら、`true`を返すようにしたいとしましょう; +そうでなければ、`false`を返すべきです。つまり、一旦`can_hold`メソッドを定義したら、リスト5-14のようなプログラムを書けるようにしたいのです。 -そして、予期される出力は以下のようになります。なぜなら、`rect2`の各寸法は`rect1`よりも小さいものの、 +予期される出力は以下のようになります。なぜなら、`rect2`の各寸法は`rect1`よりも小さいものの、 `rect3`は`rect1`より幅が広いからです: ```text @@ -294,7 +330,7 @@ read `rect2` (rather than write, which would mean we’d need a mutable borrow), and we want `main` to retain ownership of `rect2` so we can use it again after calling the `can_hold` method. The return value of `can_hold` will be a Boolean, and the implementation will check whether the width and height of -`self` are both greater than the width and height of the other `Rectangle`, +`self` are greater than the width and height of the other `Rectangle`, respectively. Let’s add the new `can_hold` method to the `impl` block from Listing 5-13, shown in Listing 5-15. --> @@ -316,21 +352,7 @@ Listing 5-13, shown in Listing 5-15. ファイル名: src/main.rs ```rust -# #[derive(Debug)] -# struct Rectangle { -# width: u32, -# height: u32, -# } -# -impl Rectangle { - fn area(&self) -> u32 { - self.width * self.height - } - - fn can_hold(&self, other: &Rectangle) -> bool { - self.width > other.width && self.height > other.height - } -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-15/src/main.rs:here}} ``` -`impl`ブロックの別の有益な機能は、`impl`ブロック内に`self`を引数に取ら*ない*関数を定義できることです。 -これは、構造体に関連付けられているので、*関連関数*と呼ばれます。それでも、関連関数は関数であり、メソッドではありません。 -というのも、対象となる構造体のインスタンスが存在しないからです。もう`String::from`という関連関数を使用したことがありますね。 +`impl`ブロック内で定義されたすべての関数は、`impl`の後に書かれた型に関連付けられているので、*関連関数*と呼ばれます。 +対象の型のインスタンスを必要としないために、`self`を第1引数として持たない(つまりメソッドではない)関連関数を定義することもできます。 +このような関数は、すでにひとつ使用しています: `String::from`関数は`String`型の上に定義された関数です。 -関連関数は、構造体の新規インスタンスを返すコンストラクタによく使用されます。例えば、一つの寸法を引数に取り、 -長さと幅両方に使用する関連関数を提供することができ、その結果、同じ値を2回指定する必要なく、 -正方形の`Rectangle`を生成しやすくすることができます。 +メソッドでない関連関数は、構造体の新規インスタンスを返すコンストラクタによく使用されます。 +これらにはしばしば`new`という名前が付けられますが、`new`は特別な名前ではなく、言語に組み込まれたものでもありません。 +例えば、一つの寸法を引数に取り、それを高さと幅の両方として使用する関連関数`square`を提供してもよいでしょう。 +そうすれば同じ値を2回指定する必要なく、正方形の`Rectangle`を生成しやすくすることができます。 + +戻り値型と関数本体内のの`Self` キーワードは`impl` キーワードの後に現れる型に対するエイリアスで、今回の場合は`Rectangle`です。 + この関連関数を呼び出すために、構造体名と一緒に`::`記法を使用します; 一例は`let sq = Rectangle::square(3);`です。 この関数は、構造体によって名前空間分けされています: `::`という記法は、関連関数とモジュールによって作り出される名前空間両方に使用されます。 -モジュールについては第7章で議論します。 +モジュールについては[第7章][modules]で議論します。 各構造体には、複数の`impl`ブロックを存在させることができます。例えば、リスト5-15はリスト5-16に示したコードと等価で、 リスト5-16では、各メソッドごとに`impl`ブロックを用意しています。 ```rust -# #[derive(Debug)] -# struct Rectangle { -# width: u32, -# height: u32, -# } -# -impl Rectangle { - fn area(&self) -> u32 { - self.width * self.height - } -} - -impl Rectangle { - fn can_hold(&self, other: &Rectangle) -> bool { - self.width > other.width && self.height > other.height - } -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-16/src/main.rs:here}} ``` @@ -472,23 +480,34 @@ useful in Chapter 10, where we discuss generic types and traits. ## まとめ -構造体により、自分の領域で意味のある独自の型を作成することができます。構造体を使用することで、 +構造体により、ドメインにとって意味のある独自の型を作成することができます。構造体を使用することで、 関連のあるデータ片を相互に結合させたままにし、各部品に名前を付け、コードを明確にすることができます。 -メソッドにより、構造体のインスタンスが行う動作を指定することができ、関連関数により、 -構造体に特有の機能をインスタンスを利用することなく、名前空間分けすることができます。 +`impl`ブロック内では型に関連付けられた関数を定義することができ、メソッドは構造体のインスタンスが持つ振る舞いを規定することができる関連関数の一種です。 しかし、構造体だけが独自の型を作成する手段ではありません: Rustのenum機能に目を向けて、 別の道具を道具箱に追加しましょう。 + + + +[enums]: ch06-00-enums.html +[trait-objects]: ch17-02-trait-objects.md +[public]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#パスをpubキーワードで公開する +[modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html diff --git a/src/ch06-00-enums.md b/src/ch06-00-enums.md index 68feb95e6..d818a0e0a 100644 --- a/src/ch06-00-enums.md +++ b/src/ch06-00-enums.md @@ -9,29 +9,20 @@ --> -この章では、*列挙型*について見ていきます。列挙型は、*enum*とも称されます。enumは、取りうる値を列挙することで、 +この章では、*列挙型*について見ていきます。列挙型は、*enum*とも称されます。enumは、取りうる*列挙子*を列挙することで、 型を定義させてくれます。最初に、enumを定義し、使用して、enumがデータとともに意味をコード化する方法を示します。 次に、特別に有用なenumである`Option`について掘り下げていきましょう。この型は、 値が何かかなんでもないかを表現します。それから、`match`式のパターンマッチングにより、 どうenumの色々な値に対して異なるコードを走らせやすくなるかを見ます。最後に、`if let`文法要素も、 如何(いか)にenumをコードで扱う際に使用可能な便利で簡潔な慣用句であるかを解説します。 - - - -enumは多くの言語に存在する機能ですが、その能力は言語ごとに異なります。Rustのenumは、F#、OCaml、Haskellなどの、 -関数型言語に存在する*代数的データ型*に最も酷似しています。 diff --git a/src/ch06-01-defining-an-enum.md b/src/ch06-01-defining-an-enum.md index ba7c87fdb..03d573975 100644 --- a/src/ch06-01-defining-an-enum.md +++ b/src/ch06-01-defining-an-enum.md @@ -4,24 +4,37 @@ ## Enumを定義する + + +構造体は、`width`と`height`を持つ`Rectangle`のように、関連するフィールドとデータをひとつにまとめる方法を提供してくれます。 +一方でenumは、ある値が、とりうる値の集合のうちのいずれかひとつであることを表現する方法を提供するものです。 +例えば、`Rectangle`は、`Circle`や`Triangle`も含めたとりうる形の集合のいずれかひとつである、と表現したいことがあります。 +これを達成するために、Rustではこれらの可能性をenumとしてエンコードすることができます。 + コードで表現したくなるかもしれない場面に目を向けて、enumが有用でこの場合、構造体よりも適切である理由を確認しましょう。 IPアドレスを扱う必要が出たとしましょう。現在、IPアドレスの規格は二つあります: バージョン4とバージョン6です。 -これらは、プログラムが遭遇するIPアドレスのすべての可能性です: 列挙型は、取りうる値をすべて*列挙*でき、 +これらはプログラムが遭遇するIPアドレスの可能性のすべてですので、取りうる列挙子をすべて*列挙*できます。 これが列挙型の名前の由来です。 この概念をコードでは、`IpAddrKind`列挙型を定義し、IPアドレスがなりうる種類、`V4`と`V6`を列挙することで、 -表現できます。これらは、enumの*列挙子*として知られています: +表現できます。これらがenumの列挙子です: ```rust -enum IpAddrKind { - V4, - V6, -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:def}} ``` enumの列挙子は、その識別子の元に名前空間分けされていることと、 @@ -91,12 +94,7 @@ enumの列挙子は、その識別子の元に名前空間分けされている 同じ型`IpAddrKind`になったからです。そうしたら、例えば、どんな`IpAddrKind`を取る関数も定義できるようになります。 ```rust -# enum IpAddrKind { -# V4, -# V6, -# } -# -fn route(ip_type: IpAddrKind) { } +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:fn}} ``` enumの利用には、さらなる利点さえもあります。このIPアドレス型についてもっと考えてみると、現状では、 実際のIPアドレスの*データ*を保持する方法がありません。つまり、どんな*種類*であるかを知っているだけです。 -構造体について第5章で学んだばっかりとすると、この問題に対して、あなたはリスト6-1のように対処するかもしれません。 +構造体について第5章で学んだばっかりとすると、この問題に対して、あなたはリスト6-1のように構造体を使って対処したくなるかもしれません。 ```rust -enum IpAddrKind { - V4, - V6, -} - -struct IpAddr { - kind: IpAddrKind, - address: String, -} - -let home = IpAddr { - kind: IpAddrKind::V4, - address: String::from("127.0.0.1"), -}; - -let loopback = IpAddr { - kind: IpAddrKind::V6, - address: String::from("::1"), -}; +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-01/src/main.rs:here}} ``` ここでは、二つのフィールドを持つ`IpAddr`という構造体を定義しています: `IpAddrKind`型(先ほど定義したenumですね)の`kind`フィールドと、 -`String`型の`address`フィールドです。この構造体のインスタンスが2つあります。最初のインスタンス、 -`home`には`kind`として`IpAddrKind::V4`があり、紐付けられたアドレスデータは`127.0.0.1`です。 -2番目のインスタンス、`loopback`には、`kind`の値として、`IpAddrKind`のもう一つの列挙子、`V6`があり、 +`String`型の`address`フィールドです。この構造体のインスタンスが2つあります。最初のインスタンスは`home`で、 +これには`kind`として`IpAddrKind::V4`があり、紐付けられたアドレスデータは`127.0.0.1`です。 +2番目のインスタンスは`loopback`です。これには`kind`の値として、`IpAddrKind`のもう一つの列挙子、`V6`があり、 アドレス`::1`が紐付いています。構造体を使って`kind`と`address`値を一緒に包んだので、 もう列挙子は値と紐付けられています。 -各enumの列挙子に直接データを格納して、enumを構造体内に使うというよりもenumだけを使って、 -同じ概念をもっと簡潔な方法で表現することができます。この新しい`IpAddr`の定義は、 -`V4`と`V6`列挙子両方に`String`値が紐付けられていることを述べています。 +しかしながら、enumだけを使って同じ概念を表現するほうがより簡潔です: +構造体の中にenumを持たせるのではなく、enumの各列挙子に直接データを格納することができるのです。 +この新しい`IpAddr`の定義は、`V4`と`V6`列挙子両方に`String`値が紐付けられていることを述べています。 ```rust -enum IpAddr { - V4(String), - V6(String), -} - -let home = IpAddr::V4(String::from("127.0.0.1")); - -let loopback = IpAddr::V6(String::from("::1")); +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/src/main.rs:here}} ``` enumの各列挙子にデータを直接添付できるので、余計な構造体を作る必要は全くありません。 +またここでは、enumがどう機能するかについての別の詳細も確認することができます: +ここで定義したenumの各列挙子の名前は、そのenumを構築する関数にもなるのです。 +つまり、`IpAddr::V4()`は`String`引数を受け取り`IpAddr`型のインスタンスを返す関数の呼び出しになるのです。 +enumを定義した結果として、自動でこのコンストラクタ関数が定義されます。 - - ```rust struct Ipv4Addr { - // 省略 + // --略-- } struct Ipv6Addr { - // 省略 + // --略-- } enum IpAddr { @@ -314,12 +276,7 @@ variety of types embedded in its variants. リスト6-2でenumの別の例を見てみましょう: 今回のコードは、幅広い種類の型が列挙子に埋め込まれています。 ```rust -enum Message { - Quit, - Move { x: i32, y: i32 }, - Write(String), - ChangeColor(i32, i32, i32), -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-02/src/main.rs:here}} ``` -* `Quit`には紐付けられたデータは全くなし。 -* `Move`は、中に匿名構造体を含む。 -* `Write`は、単独の`String`オブジェクトを含む。 -* `ChangeColor`は、3つの`i32`値を含む。 +* `Quit`は関連付けられたデータをまったく持ちません。 +* `Move`は構造体のように名前付きのフィールドを持っています。 +* `Write`は`String`オブジェクトを1個だけ含んでいます。 +* `ChangeColor`は3個の`i32`値を含んでいます。 - ```rust -struct QuitMessage; // ユニット構造体 -struct MoveMessage { - x: i32, - y: i32, -} -struct WriteMessage(String); // タプル構造体 -struct ChangeColorMessage(i32, i32, i32); // タプル構造体 +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs:here}} ``` - - -ですが、異なる構造体を使っていたら、各々、それ自身の型があるので、単独の型になるリスト6-2で定義した`Message` enumほど、 -これらの種のメッセージいずれもとる関数を簡単に定義することはできないでしょう。 +ですがそれぞれ独自の型を持つ異なる構造体を使ってしまうと、リスト6-2で定義した単一の型である`Message` enumを使う場合と比較して、 +これらの任意の種類のメッセージを取る関数を簡単には定義できません。 -前節で、`IpAddr` enumがRustの型システムを使用して、プログラムにデータ以上の情報をコード化できる方法を目撃しました。 この節では、`Option`のケーススタディを掘り下げていきます。この型も標準ライブラリにより定義されているenumです。 -この`Option`型はいろんな箇所で使用されます。なぜなら、値が何かかそうでないかという非常に一般的な筋書きをコード化するからです。 -この概念を型システムの観点で表現することは、コンパイラが、プログラマが処理すべき場面全てを処理していることをチェックできることを意味します; +この`Option`型は、値が何かかそうでないかという非常に一般的な筋書きをコード化します。 + + + +例えば、空でないリストの最初のアイテムをリクエストすると、値が得られるでしょう。 +空リストの最初のアイテムをリクエストすると、何も得られないでしょう。 +この概念を型システムの観点で表現することは、コンパイラが、プログラマが処理すべき場面全てを処理しているかどうかチェックできることを意味します; この機能は、他の言語において、究極的にありふれたバグを阻止することができます。 -`Option`は有益すぎて、初期化処理(prelude)にさえ含まれています。つまり、明示的にスコープに導入する必要がないのです。 -さらに、列挙子もそうなっています: `Some`と`None`を`Option::`の接頭辞なしに直接使えるわけです。 -ただ、`Option`はそうは言っても、普通のenumであり、`Some(T)`と`None`も`Option`型のただの列挙子です。 +`Option`は有益すぎて、preludeにさえ含まれています; 明示的にスコープに導入する必要がないのです。 +そしてその列挙子もまたpreludeに含まれています: `Some`と`None`を`Option::`の接頭辞なしに直接使えるわけです。 +ただ、`Option` enumはそうは言っても、普通のenumであり、`Some(T)`と`None`も`Option`型のただの列挙子です。 -``という記法は、まだ語っていないRustの機能です。これは、ジェネリック型引数であり、ジェネリクスについて詳しくは、 -第10章で解説します。とりあえず、知っておく必要があることは、``は、`Option` enumの`Some`列挙子が、 -あらゆる型のデータを1つだけ持つことができることを意味していることだけです。こちらは、 -`Option`値を使って、数値型や文字列型を保持する例です。 +``という記法は、まだ語っていないRustの機能です。 +これはジェネリック型引数で、ジェネリクスについて詳しくは第10章で解説します。 +とりあえず``の意味に関して知っておく必要があることは、`Option` enumの`Some`列挙子はあらゆる型のデータを1つだけ持つことができ、 +`T`の代わりに使用される具体的な型に応じて、`Option`型はそれぞれ異なる型になるということだけです。 +以下は`Option`値を使って数値型や文字列型を保持する例です。 ```rust -let some_number = Some(5); -let some_string = Some("a string"); - -let absent_number: Option = None; +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs:here}} ``` -`Some`ではなく、`None`を使ったら、コンパイラに`Option`の型が何になるかを教えなければいけません。 -というのも、`None`値を見ただけでは、`Some`列挙子が保持する型をコンパイラが推論できないからです。 +`some_number`の型は`Option`です。`some_char`の型は`Option`で、これは先ほどとは異なる型です。 +`Some`列挙子の中で値を指定しているので、コンパイラはこれらの型を推論することができます。 +`absent_number`に関しては、コンパイラはジェネリクス適用後の`Option`型を注釈することを要求します: +`None`値を見ただけでは、それに対応する`Some`列挙子が保持する型をコンパイラは推論できないからです。 +ここでは、`absent_number`が`Option`型を持つことをコンパイラに伝えています。 `Some`値がある時、値が存在するとわかり、その値は、`Some`に保持されています。`None`値がある場合、 @@ -594,8 +524,8 @@ nullよりも少しでも好ましいのでしょうか? @@ -603,28 +533,18 @@ trying to add an `i8` to an `Option`: コンパイラが`Option`値を確実に有効な値かのようには使用させてくれません。 例えば、このコードは`i8`を`Option`に足そうとしているので、コンパイルできません。 -```rust,ignore -let x: i8 = 5; -let y: Option = Some(5); - -let sum = x + y; +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/src/main.rs:here}} ``` このコードを動かしたら、以下のようなエラーメッセージが出ます。 -```text -error[E0277]: the trait bound `i8: std::ops::Add>` is -not satisfied -(エラー: `i8: std::ops::Add>`というトレイト境界が満たされていません) - --> - | -5 | let sum = x + y; - | ^ no implementation for `i8 + std::option::Option` - | +```console +{{#include ../listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt}} ``` 言い換えると、`T`型の処理を行う前には、`Option`を`T`に変換する必要があるわけです。一般的に、 @@ -657,7 +576,7 @@ is. そうでないかのように想定することです。 -不正確にnullでない値を想定する心配をしなくてもよいということは、コード内でより自信を持てることになります。 +値がnullでないと誤って想定するリスクを削減することは、コードに確信を持つための助けになります。 nullになる可能性のある値を保持するには、その値の型を`Option`にすることで明示的に同意しなければなりません。 それからその値を使用する際には、値がnullである場合を明示的に処理する必要があります。 値が`Option`以外の型であるところ全てにおいて、値がnullでないと安全に想定することが*できます*。 これは、Rustにとって、意図的な設計上の決定であり、nullの普遍性を制限し、Rustコードの安全性を向上させます。 では、`Option`型の値がある時、その値を使えるようにするには、どのように`Some`列挙子から`T`型の値を取り出せばいいのでしょうか? @@ -686,21 +606,29 @@ the methods on `Option` will be extremely useful in your journey with Rust. [ドキュメント][docs]でそれらを確認できます。`Option`のメソッドに馴染むと、 Rustの旅が極めて有益になるでしょう。 -[docs]: https://doc.rust-lang.org/std/option/enum.Option.html - 一般的に、`Option`値を使うには、各列挙子を処理するコードが欲しくなります。 -`Some(T)`値がある時だけ走る何らかのコードが欲しくなり、このコードが内部の`T`を使用できます。 -`None`値があった場合に走る別のコードが欲しくなり、そちらのコードは`T`値は使用できない状態になります。 +`Some(T)`値がある場合だけ走る何らかのコードが欲しくなり、このコードが内部の`T`を使用できます。 +`None`値がある場合だけ走る別のコードが欲しくなり、そちらのコードは`T`を使用できない状態になります。 `match`式が、enumとともに使用した時にこれだけの動作をする制御フロー文法要素になります: enumの列挙子によって、違うコードが走り、そのコードがマッチした値の中のデータを使用できるのです。 + + + +[IpAddr]: https://doc.rust-lang.org/std/net/enum.IpAddr.html +[option]: https://doc.rust-lang.org/std/option/enum.Option.html +[docs]: https://doc.rust-lang.org/std/option/enum.Option.html diff --git a/src/ch06-02-match.md b/src/ch06-02-match.md index f0fe802b4..968bedb2f 100644 --- a/src/ch06-02-match.md +++ b/src/ch06-02-match.md @@ -1,26 +1,32 @@ + -## `match`制御フロー演算子 + + +## `match`制御フロー構造 Rustには、一連のパターンに対して値を比較し、マッチしたパターンに応じてコードを実行させてくれる`match`と呼ばれる、 -非常に強力な制御フロー演算子があります。パターンは、リテラル値、変数名、ワイルドカードやその他多数のもので構成することができます; -第18章で、全ての種類のパターンと、その目的については解説します。`match`のパワーは、 +非常に強力な制御フロー構造があります。パターンは、リテラル値、変数名、ワイルドカードやその他多数のもので構成することができます; +[第18章][ch18-00-patterns]で、全ての種類のパターンと、その目的については解説します。`match`のパワーは、 パターンの表現力とコンパイラが全てのありうるパターンを処理しているかを確認してくれるという事実に由来します。 -コインについて話したので、それを`match`を使用する例にとってみましょう!数え上げ装置と同じ要領で未知のアメリカコインを一枚取り、 +せっかくコインについて話したので、それを`match`を使用する例にとってみましょう!数え上げ装置と同じ要領で未知のアメリカコインを一枚取り、 どの種類のコインなのか決定し、その価値をセントで返す関数をリスト6-3で示したように記述することができます。 ```rust -enum Coin { - Penny, - Nickel, - Dime, - Quarter, -} - -fn value_in_cents(coin: Coin) -> u32 { - match coin { - Coin::Penny => 1, - Coin::Nickel => 5, - Coin::Dime => 10, - Coin::Quarter => 25, - } -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-03/src/main.rs:here}} ``` リスト6-3: enumとそのenumの列挙子をパターンにした`match`式 `value_in_cents`関数内の`match`を噛み砕きましょう。まず、`match`キーワードに続けて式を並べています。 -この式は今回の場合、値`coin`です。`if`で使用した式と非常に酷似しているみたいですね。しかし、大きな違いがあります: -`if`では、式は論理値を返す必要がありますが、ここでは、どんな型でも構いません。この例における`coin`の型は、 +この式は今回の場合、値`coin`です。`if`で使用した条件式と非常に酷似しているみたいですね。しかし、大きな違いがあります: +`if`では、条件は論理値に評価される必要がありますが、ここでは、どんな型でも構いません。この例における`coin`の型は、 1行目で定義した`Coin` enumです。 @@ -112,47 +104,32 @@ entire `match` expression. 各アームに紐付けられるコードは式であり、マッチしたアームの式の結果が`match`式全体の戻り値になります。 -典型的に、アームのコードが短い場合、波かっこは使用されません。リスト6-3では、各アームが値を返すだけなので、 -これに倣っています。マッチのアームで複数行のコードを走らせたいのなら、波かっこを使用することができます。 +典型的に、アームのコードが短い場合、波かっこは使用しません。リスト6-3では、各アームが値を返すだけなので、 +これに倣っています。マッチのアームで複数行のコードを走らせたいのなら、波かっこを使わなくてはなりませんが、 +この場合アームの後のカンマは省略することができます。 例えば、以下のコードは、メソッドが`Coin::Penny`とともに呼び出されるたびに「Lucky penny!」と表示しつつ、 -ブロックの最後の値、`1`を返すでしょう。 +ブロックの最後の値、`1`を返します。 ```rust -# enum Coin { -# Penny, -# Nickel, -# Dime, -# Quarter, -# } -# -fn value_in_cents(coin: Coin) -> u32 { - match coin { - Coin::Penny => { - println!("Lucky penny!"); - 1 - }, - Coin::Nickel => 5, - Coin::Dime => 10, - Coin::Quarter => 25, - } -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/src/main.rs:here}} ``` ### 値に束縛されるパターン @@ -165,8 +142,8 @@ As an example, let’s change one of our enum variants to hold data inside it. From 1999 through 2008, the United States minted quarters with different designs for each of the 50 states on one side. No other coins got state designs, so only quarters have this extra value. We can add this information to -our `enum` by changing the `Quarter` variant to include a `UsState` value stored -inside it, which we've done here in Listing 6-4. +our `enum` by changing the `Quarter` variant to include a `UsState` value +stored inside it, which we’ve done in Listing 6-4. --> 例として、enumの列挙子の一つを中にデータを保持するように変えましょう。1999年から2008年まで、 @@ -175,40 +152,8 @@ inside it, which we've done here in Listing 6-4. `Quarter`列挙子を変更して、`UsState`値が中に保持されるようにすることで`enum`にこの情報を追加でき、 それをしたのがリスト6-4のコードになります。 - - - - -```rust -#[derive(Debug)] // すぐに州を点検できるように -enum UsState { - Alabama, - Alaska, - // ... などなど -} - -enum Coin { - Penny, - Nickel, - Dime, - Quarter(UsState), -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs:here}} ``` @@ -240,30 +185,7 @@ quarter’s state. Then we can use `state` in the code for that arm, like so: `state`をそのアームのコードで使用できます。以下のようにですね: ```rust -# #[derive(Debug)] -# enum UsState { -# Alabama, -# Alaska, -# } -# -# enum Coin { -# Penny, -# Nickel, -# Dime, -# Quarter(UsState), -# } -# -fn value_in_cents(coin: Coin) -> u32 { - match coin { - Coin::Penny => 1, - Coin::Nickel => 5, - Coin::Dime => 10, - Coin::Quarter(state) => { - println!("State quarter from {:?}!", state); - 25 - }, - } -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/src/main.rs:here}} ``` 前節では、`Option`を使用する際に、`Some`ケースから中身の`T`の値を取得したくなりました。要するに、 @@ -317,16 +239,7 @@ Listing 6-5. `match`のおかげで、この関数は大変書きやすく、リスト6-5のような見た目になります。 ```rust -fn plus_one(x: Option) -> Option { - match x { - None => None, - Some(i) => Some(i + 1), - } -} - -let five = Some(5); -let six = plus_one(five); -let none = plus_one(None); +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:here}} ``` `plus_one`の最初の実行についてもっと詳しく検証しましょう。`plus_one(five)`と呼び出した時、 -`plus_one`の本体の変数`x`は`Some(5)`になります。そして、これをマッチの各アームと比較します。 +`plus_one`の本体の変数`x`は`Some(5)`になります。そして、これをマッチの各アームと比較します: ```rust,ignore -None => None, +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:first_arm}} ``` -`Some(5)`という値は、`None`というパターンにはマッチしませんので、次のアームに処理が移ります。 +`Some(5)`という値は、`None`というパターンにはマッチしませんので、次のアームに処理が移ります: ```rust,ignore -Some(i) => Some(i + 1), +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:second_arm}} ``` - -`Some(5)`は`Some(i)`にマッチしますか?なんと、します!列挙子が同じです。`i`は`Some`に含まれる値に束縛されるので、 +`Some(5)`は`Some(i)`にマッチしますか?しますね!列挙子が同じです。`i`は`Some`に含まれる値に束縛されるので、 `i`は値`5`になります。それから、このマッチのアームのコードが実行されるので、`i`の値に1を足し、 合計の`6`を中身にした新しい`Some`値を生成します。 さて、`x`が`None`になるリスト6-5の2回目の`plus_one`の呼び出しを考えましょう。`match`に入り、 -最初のアームと比較します。 +最初のアームと比較します: ```rust,ignore -None => None, +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:first_arm}} ``` -もう一つ議論する必要のある`match`の観点があります。一点バグがありコンパイルできないこんなバージョンの`plus_one`関数を考えてください: +もう一つ議論する必要のある`match`の観点があります: アームのパターンはすべての可能性を網羅しなくてはなりません。 +こんなバージョンの`plus_one`関数を考えてください、これにはバグがありコンパイルできないでしょう: -```rust,ignore -fn plus_one(x: Option) -> Option { - match x { - Some(i) => Some(i + 1), - } -} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/src/main.rs:here}} ``` - | -6 | match x { - | ^ pattern `None` not covered +```console +{{#include ../listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt}} ``` 全可能性を網羅していないことをコンパイラは検知しています。もっと言えば、どのパターンを忘れているかさえ知っているのです。 Rustにおけるマッチは、*包括的*です: 全てのあらゆる可能性を網羅し尽くさなければ、コードは有効にならないのです。 特に`Option`の場合には、私達が明示的に`None`の場合を処理するのを忘れないようにしてくれます。 -nullになるかもしれないのに値があると思い込まないよう、すなわち前に議論した10億ドルの失敗を犯さないよう、 +nullになるかもしれないのに値があると思い込まないよう、すなわち前に議論した10億ドルの失敗を犯すことができないよう、 コンパイラが保護してくれるわけです。 -### `_`というプレースホルダー +### catch-allパターンとプレースホルダー(`_`) -Rustには、全ての可能性を列挙したくない時に使用できるパターンもあります。例えば、`u8`は、有効な値として、 -0から255までを取ります。1、3、5、7の値にだけ興味があったら、0、2、4、6、8、9と255までの数値を列挙する必要に迫られたくはないです。 -幸運なことに、する必要はありません: 代わりに特別なパターンの`_`を使用できます: +enumを使用することで、いくつかの特定の値に対して特別な操作を行うが、他のすべての値に対してはデフォルトの操作を行う、ということができます。 +ゲームを実装しているところを想像してください。 +サイコロを振って3の目が出たら、そのプレイヤーは移動できませんが、代わりにおしゃれな帽子をもらえます。 +サイコロを振って7の目が出たら、そのプレイヤーはおしゃれな帽子を失います。 +他のすべての値については、そのプレイヤーはゲーム盤上で同じ数だけマスを移動します。 +以下はこのロジックを実装する`match`です。 +ただしサイコロを振った結果はランダム値ではなくハードコードされており、また他のすべてのロジックは、それを実際に実装するのは本題ではないので、本体の無い関数によって表現されています: ```rust -let some_u8_value = 0u8; -match some_u8_value { - 1 => println!("one"), - 3 => println!("three"), - 5 => println!("five"), - 7 => println!("seven"), - _ => (), -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs:here}} ``` + +最初の2つのアームについては、パターンはリテラル値`3`および`7`です。 +他のあらゆる可能な値を網羅する最後のアームについては、パターンは変数で、この変数には`other`と名付けることを選びました。 +`other`アームで実行されるコードは、`move_player`関数にこの変数を渡すことで、この変数を使用しています。 + + + +`u8`が取りうるすべての値を列挙していないにも関わらず、このコードはコンパイルできます。 +最後のパターンが、個別に列挙していないすべての値にマッチするからです。 +このcatch-allパターンのおかげで、`match`は包括的でなくてはならないという必要条件が満たされます。 +パターンは順に評価されるので、catch-allアームは最後に書く必要があることに注意してください。 +catch-allアームを先に書いてしまうと他のアームは絶対に実行されなくなってしまうため、 +catch-allの後にアームを追加するとコンパイラが警告を発するでしょう! + + + +Rustには、catch-allしたいが、catch-allパターン内で値を*使用*したくない時に使用できるパターンもあります: +`_`は任意の値にマッチし、その値を束縛しない特別なパターンです。 +これはコンパイラにその値を使用しないということを伝えるので、コンパイラは未使用の変数についての警告を発しなくなるしょう。 + + + +ゲームのルールを変更しましょう: これからは、3または7以外の目を出したら、もう一度サイコロを振らなくてはなりません。 +catch-allの値を使用する必要がなくなるので、`other`変数の代わりに`_`を使用するようにコードを変更します: + + +```rust +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs:here}} +``` + + + +この例もまた、最後のアームで明示的にすべての他の値を無視しているので、網羅性要件を満たしています; +見落としている場合分けはありません。 + + + +最後に、もう一度だけゲームのルールを変更することにします。 +3または7以外の目を出したら、プレイヤーの番には何も起きません。 +以下の`_`アームのコードのように、ユニット値([「タプル型」][tuples]節で説明した空タプル型)を使用することでこれを表現できます: + +```rust +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs:here}} +``` + + + +このコードでは、先の方のアームのパターンにマッチしないあらゆる値は使用せず、 +この場合にはいかなるコードも実行したくないということを、コンパイラに明示的に伝えています。 + + -`_`というパターンは、どんな値にもマッチします。他のアームの後に記述することで、`_`は、 -それまでに指定されていない全ての可能性にマッチします。`()`は、ただのユニット値なので、`_`の場合には、 -何も起こりません。結果として、`_`プレースホルダーの前に列挙していない可能性全てに対しては、 -何もしたくないと言えるわけです。 +パターンとマッチングについては[第18章][ch18-00-patterns]でさらに深く取り扱います。 +ひとまず、`match`式ではちょっと長ったらしいという状況で便利かもしれない、`if let`構文に進むことにましょう。 -ですが、*一つ*のケースにしか興味がないような場面では、`match`式はちょっと長ったらしすぎます。 -このような場面用に、Rustには、`if let`が用意されています。 +[tuples]: ch03-02-data-types.html#タプル型 +[ch18-00-patterns]: ch18-00-patterns.html diff --git a/src/ch06-03-if-let.md b/src/ch06-03-if-let.md index e946ce219..057123639 100644 --- a/src/ch06-03-if-let.md +++ b/src/ch06-03-if-let.md @@ -7,38 +7,36 @@ `if let`記法で`if`と`let`をより冗長性の少ない方法で組み合わせ、残りを無視しつつ、一つのパターンにマッチする値を扱うことができます。 -`Option`にマッチするけれど、値が3の時にだけコードを実行したい、リスト6-6のプログラムを考えてください。 +`config_max`変数の`Option`値にマッチするけれど、値が`Some`列挙子の時にだけコードを実行したい、リスト6-6のプログラムを考えてください。 ```rust -let some_u8_value = Some(0u8); -match some_u8_value { - Some(3) => println!("three"), - _ => (), -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs:here}} ``` -リスト6-6: 値が`Some(3)`の時だけコードを実行する`match` +リスト6-6: 値が`Some`の時だけコードを実行する`match` -`Some(3)`にマッチした時だけ何かをし、他の`Some`値や`None`値の時には何もしたくありません。 -`match`式を満たすためには、列挙子を一つだけ処理した後に`_ => ()`を追加しなければなりません。 -これでは、追加すべき定型コードが多すぎます。 +値が`Some`の場合は、その`Some`列挙子の値をパターン内の変数`max`に束縛することで、それを出力します。 +`None`値に対しては何もしたくありません。 +`match`式の要件を満たすためには、列挙子を一つだけ処理した後に`_ => ()`を追加しなければなりませんが、これは煩わしい定型コードです。 -`if let`という記法は等号記号で区切られたパターンと式を取り、式が`match`に与えられ、パターンが最初のアームになった`match`と、 -同じ動作をします。 +`if let`という記法は等号記号で区切られたパターンと式を取り、式が`match`に与えられ、パターンが最初のアームになった`match`と同じ動作をします。 +この場合は、パターンは`Some(max)`で`max`は`Some`内の値に束縛されます。 +そうすると、対応する`match`アームの中で`max`を使用したのと全く同じように、`if let`ブロックの本体の中で`max`を使用することができます。 +値がパターンにマッチしない場合は、`if let`ブロック内のコードは実行されません。 `if let`では、`else`を含むこともできます。`else`に入るコードブロックは、 @@ -101,53 +102,17 @@ expression like this: 見かけたクォーター以外のコインの枚数を数えたいなら、以下のように`match`式で実現することができるでしょう: ```rust -# #[derive(Debug)] -# enum UsState { -# Alabama, -# Alaska, -# } -# -# enum Coin { -# Penny, -# Nickel, -# Dime, -# Quarter(UsState), -# } -# let coin = Coin::Penny; -let mut count = 0; -match coin { - // {:?}州のクォーターコイン - Coin::Quarter(state) => println!("State quarter from {:?}!", state), - _ => count += 1, -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs:here}} ``` または、以下のように`if let`と`else`を使うこともできるでしょう: ```rust -# #[derive(Debug)] -# enum UsState { -# Alabama, -# Alaska, -# } -# -# enum Coin { -# Penny, -# Nickel, -# Dime, -# Quarter(UsState), -# } -# let coin = Coin::Penny; -let mut count = 0; -if let Coin::Quarter(state) = coin { - println!("State quarter from {:?}!", state); -} else { - count += 1; -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs:here}} ``` diff --git a/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md b/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md index 77ed82d97..415f39404 100644 --- a/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md +++ b/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md @@ -4,44 +4,43 @@ # 肥大化していくプロジェクトをパッケージ、クレート、モジュールを利用して管理する -大きなプログラムを書く時、そのすべてを頭の中に入れておくのは不可能になるため、コードのまとまりを良くすることが重要になります。 +書いているプログラムが大きいときほど、コードを整理しておくことはますます重要になります。 関係した機能をまとめ、異なる特徴を持つコードを分割することにより、特定の機能を実装しているコードを見つけたり、機能を変更したりするためにどこを探せば良いのかを明確にできます。 私達がこれまでに書いてきたプログラムは、一つのファイル内の一つのモジュール内にありました。 -プロジェクトが大きくなるにつれて、これを複数のモジュールに、ついで複数のファイルに分割することで、プログラムを整理することができます。 +プロジェクトが大きくなるにつれて、これを複数のモジュールに、ついで複数のファイルに分割することで、プログラムを整理するべきです。 パッケージは複数のバイナリクレートからなり、またライブラリクレートを1つもつこともできます。 パッケージが大きくなるにつれて、その一部を抜き出して分離したクレートにし、外部依存とするのもよいでしょう。 この章ではそれらのテクニックすべてを学びます。 相互に関係し合い、同時に成長するパッケージの集まりからなる巨大なプロジェクトには、 -Cargoがワークスペースという機能を提供します。これは14章の[Cargoワークスペース][workspaces]で解説します。 +Cargoが*ワークスペース*という機能を提供します。これは14章の[Cargoワークスペース][workspaces]で解説します。 -機能をグループにまとめられることに加え、実装の詳細がカプセル化されることにより、コードをより高いレベルで再利用できるようになります: -手続きを実装し終えてしまえば、他のコードはそのコードの公開されたインターフェースを通じて、実装の詳細を知ることなくそのコードを呼び出すことができるのです。 +実装の詳細をカプセル化することについても議論します。カプセル化によって、コードをより高いレベルで再利用できるようになります: +手続きを実装し終えてしまえば、他のコードはその公開されたインターフェースを通じて、実装の詳細を知る必要なくそのコードを呼び出すことができるのです。 コードをどう書くかによって、どの部分が他のコードにも使える公開のものになるのか、それとも自分だけが変更できる非公開のものになるのかが決定されます。 これもまた、記憶しておくべき細部を制限してくれる方法のひとつです。 diff --git a/src/ch07-01-packages-and-crates.md b/src/ch07-01-packages-and-crates.md index 05320c41e..fd5417e1d 100644 --- a/src/ch07-01-packages-and-crates.md +++ b/src/ch07-01-packages-and-crates.md @@ -4,29 +4,80 @@ ## パッケージとクレート 最初に学ぶモジュールシステムの要素は、パッケージとクレートです。 -クレートはバイナリかライブラリのどちらかです。 -*クレートルート (crate root)* とは、Rustコンパイラの開始点となり、クレートのルートモジュールを作るソースファイルのことです(モジュールについて詳しくは[「モジュールを定義して、スコープとプライバシーを制御する」][modules]のセクションで説明します)。 -*パッケージ* はある機能群を提供する1つ以上のクレートです。 + + +*クレート (crate)* は、Rustコンパイラが一度に考慮する最小限のコードです。 +`cargo`を実行するのではなく、(ちょうど第1章の「Rustプログラムを書いて走らせる」節でやったように)単一のソースコードファイルを渡して`rustc`を実行した場合でも、 +コンパイラはそのファイルをクレートとしてみなします。 +クレートはモジュールを含むことができ、モジュールは、クレートとともにコンパイルされる他のファイル内で定義することができます。 +このことについてはこれからの節で見ていきます。 + + +クレートは2種類の形態のうちいずれかです: バイナリクレートか、ライブラリクレートです。 +*バイナリクレート (binary crate)* は、コマンドラインプログラムやサーバなどの実行可能形式にコンパイルされ、実行することができるプログラムです。 +どのバイナリクレートも、その実行可能形式が実行されたときに何が起きるかを定義する`main`と呼ばれる関数を持たなくてはなりません。 +今まで作ってきたクレートはすべてバイナリクレートでした。 + + +*ライブラリクレート (library crate)* は`main`関数を持たず、実行可能形式へとコンパイルされません。 +代わりに、複数のプロジェクトで共有されることを想定した機能を定義するものです。 +例えば、[第2章][rand]で使用した`rand`クレートは乱数を生成する機能を提供します。 +Rustaceanが「クレート」と言うときの、ほとんどの場合それはライブラリクレートのことであり、 +Rustaceanは「クレート」を一般的なプログラミング概念の「ライブラリ」と同じ意味で使用します。 + + +*クレートルート (crate root)* とは、Rustコンパイラの開始点となり、クレートのルートモジュールを作るソースファイルのことです(モジュールについて詳しくは[「モジュールを定義して、スコープとプライバシーを制御する」][modules]のセクションで説明します)。 + + +*パッケージ (package)* はある機能群を提供する1つ以上のクレートのまとまりです。 パッケージは *Cargo.toml* という、それらのクレートをどのようにビルドするかを説明するファイルを持っています。 +Cargoは実のところパッケージで、今までコードをビルドするために使ってきたコマンドラインツールのためのバイナリクレートを含んでいます。 +Cargoパッケージは、このバイナリクレートが依存するライブラリクレートも含んでいます。 +他のプロジェクトはCargoライブラリクレートに依存することで、Cargoコマンドラインツールが使用するのと同じロジックを使用することもできます。 -パッケージが何を持ってよいかはいくつかのルールで決まっています。 -パッケージは0個か1個のライブラリクレートを持っていないといけません。それ以上は駄目です。 -バイナリクレートはいくらでも持って良いですが、少なくとも(ライブラリでもバイナリでも良いですが)1つのクレートを持っていないといけません。 +パッケージは好きなだけバイナリクレートを持つことができますが、ライブラリクレートは最大で1個しか持つことができません。 +パッケージはライブラリクレートかバイナリクレートを問わず、少なくとも1個のクレートを持っていないといけません。 -このコマンドを入力したとき、Cargoは *Cargo.toml* ファイルを作り、パッケージを作ってくれました。 -*Cargo.toml* の中身を見ても、*src/main.rs* については何も書いてありません。これは、Cargoは *src/main.rs* が、パッケージと同じ名前を持つバイナリクレートのクレートルートであるという慣習に従っているためです。 +`cargo new`を実行した後、Cargoが作成したものを確認するために`ls`を使っています。 +プロジェクトディレクトリ内には *Cargo.toml* ファイルがあり、これがパッケージを構成します。 +また、*main.rs* を含む *src* ディレクトリもあります。 +*Cargo.toml* をテキストエディタで開くと、*src/main.rs* については何も書いていないことに気づくでしょう。 +Cargoは *src/main.rs* が、パッケージと同じ名前を持つバイナリクレートのクレートルートであるという慣習に従っています。 同じように、Cargoはパッケージディレクトリに *src/lib.rs* が含まれていたら、パッケージにはパッケージと同じ名前のライブラリクレートが含まれており、*src/lib.rs* がそのクレートルートなのだと判断します。 Cargoはクレートルートファイルを `rustc`に渡し、ライブラリやバイナリをビルドします。 今、このパッケージには *src/main.rs* しか含まれておらず、つまりこのパッケージは`my-project`という名前のバイナリクレートのみを持っているということです。 -もしパッケージが *src/main.rs* と *src/lib.rs* を持っていたら、クレートは2つになります:どちらもパッケージと同じ名前を持つ、ライブラリクレートとバイナリクレートです。 +もしパッケージが *src/main.rs* と *src/lib.rs* を持っていたら、クレートは2つになります:どちらもパッケージと同じ名前を持つ、バイナリクレートとライブラリクレートです。 ファイルを *src/bin* ディレクトリに置くことで、パッケージは複数のバイナリクレートを持つことができます。それぞれのファイルが別々のバイナリクレートになります。 - - -クレートは、関連した機能を一つのスコープにまとめることで、その機能が複数のプロジェクト間で共有しやすいようにします。 -例えば、[2章][rand]で使った`rand`クレートは、乱数を生成する機能を提供します。 -`rand`クレートを私達のプロジェクトのスコープに持ち込むことで、この機能を私達のプロジェクトで使うことができます。 -`rand`クレートが提供する機能にはすべて、クレートの名前`rand`を使ってアクセスできます。 - - -クレートの機能をそれ自身のスコープの中に入れたままにしておくことは、ある機能が私達のクレートで定義されたのか`rand`クレートで定義されたのかを明確にし、名前の衝突を予防してくれます。 -例えば、`rand`クレートは`Rng`という名前のトレイトを提供しています。 -更に、私達のクレートで`Rng`という名前の`struct`を定義することもできます。 -クレートの機能はそのスコープ内の名前空間に位置づけられているので、`rand`を依存先として追加しても、コンパイラは`Rng`という名前が何を意味するのかについて混乱することはないのです。 -私達のクレートでは、私達の定義した`struct Rng`のことであり、`rand`クレートの`Rng`トレイトには`rand::Rng`でアクセスするというわけです。 - -では、モジュールシステムの話に移りましょう! - [modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html [rand]: ch02-00-guessing-game-tutorial.html#乱数を生成する diff --git a/src/ch07-02-defining-modules-to-control-scope-and-privacy.md b/src/ch07-02-defining-modules-to-control-scope-and-privacy.md index 87c77098d..4ced90bcc 100644 --- a/src/ch07-02-defining-modules-to-control-scope-and-privacy.md +++ b/src/ch07-02-defining-modules-to-control-scope-and-privacy.md @@ -7,86 +7,238 @@ In this section, we’ll talk about modules and other parts of the module system, namely *paths* that allow you to name items; the `use` keyword that brings a path into scope; and the `pub` keyword to make items public. We’ll also discuss -the `as` keyword, external packages, and the glob operator. For now, let’s -focus on modules! +the `as` keyword, external packages, and the glob operator. --> この節では、モジュールと、その他のモジュールシステムの要素 ――すなわち、要素に名前をつけるための *パス* 、パスをスコープに持ち込む`use`キーワード、要素を公開する`pub`キーワード―― について学びます。 また、`as`キーワード、外部パッケージ、glob演算子についても話します。 -とりあえず、今はモジュールに集中しましょう! -*モジュール* はクレート内のコードをグループ化し、可読性と再利用性を上げるのに役に立ちます。 -モジュールは要素の *プライバシー* も制御できます。プライバシーとは、要素がコードの外側で使える *(公開 public)* のか、内部の実装の詳細であり外部では使えない *(非公開 private)* のかです。 +まずは、将来コードを整理するときの簡単なリファレンスとして、規則の一覧を示します。 +その後で各規則を詳細に説明します。 + + +### モジュールのチートシート + + +以下に、モジュール、パス、`use`キーワード、そして`pub`キーワードがコンパイラ内でどう機能するか、そして多くの開発者はどのようにコードを整理するかについての、クイックリファレンスを提供します。 +この章ではこれらの各規則の実例を見ていきますが、ここはモジュールがどう機能するか思い出すために見直すのに良い場所となるでしょう。 + + +- **クレートルートから始める**: クレートをコンパイルするとき、 + コンパイラはまずコンパイル対象のコードとしてクレートルートファイル(通常は、ライブラリクレートでは *src/lib.rs*、バイナリクレートでは *src/main.rs*)の中を探します。 +- **モジュールを宣言する**: クレートルートファイルの中で、新しいモジュールを宣言することができます; + 例えば、`mod garden;`として“garden”モジュールを宣言したとします。コンパイラは以下の場所からモジュールのコードを探します: + - インライン。`mod garden`の後のセミコロンが波かっこで置き換えられているとき、その中 + - *src/garden.rs* ファイルの中 + - *src/garden/mod.rs* ファイルの中 +- **サブモジュールを宣言する**: クレートルート以外のすべてのファイルの中で、サブモジュールを宣言することができます。 + 例えば、*src/garden.rs* 内で`mod vegetables;`と宣言することができます。コンパイラはサブモジュールのコードを、親モジュールに対応するディレクトリ内の以下の場所から探します: + - インライン。`mod vegetables`のすぐ後にセミコロンの代わりに波かっこがあるとき、その中 + - *src/garden/vegetables.rs* ファイルの中 + - *src/garden/vegetables/mod.rs* ファイルの中 +- **モジュール内のコードへのパス**: モジュールがクレートの一部となったら、プライバシー規則が許す限り同じクレート内のどこからでも、そのモジュール内のコードをコードへのパスを使用して参照できます。 + 例えば、garden vegetablesモジュール内の`Asparagus`型は`crate::garden::vegetables::Asparagus`で参照できます。 +- **非公開と公開**: モジュール内のコードはデフォルトでは非公開で、親モジュールからアクセスすることができません。 + モジュールを公開にするには、`mod`ではなく`pub mod`で宣言してください。 + 公開モジュール内の要素も公開にするには、それらの宣言の前に`pub`を付けてください。 +- **`use`キーワード**: `use`キーワードは、長いパスの繰り返しを減らすために、要素へのショートカットをスコープ内に作成します。 + `crate::garden::vegetables::Asparagus`を参照できるスコープ内であれば、`use crate::garden::vegetables::Asparagus;`でショートカットを作成でき、 + 以降はそのスコープ内ではその型を使用するためには`Asparagus`とだけ書けばよくなります。 + + +これらの規則を説明するための例として、ここに`backyard`という名前のバイナリクレートを作成します。 +クレートのディレクトリは、同じく`backyard`と名付けられ、以下のファイルとディレクトリを含んでいます: + +```text +backyard +├── Cargo.lock +├── Cargo.toml +└── src + ├── garden + │   └── vegetables.rs + ├── garden.rs + └── main.rs +``` + + +この場合のクレートルートファイルは *src/main.rs* であり、以下の内容を含んでいます: + + +ファイル名: src/main.rs + +```rust,noplayground,ignore +{{#rustdoc_include ../listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs}} +``` + + +`pub mod garden;`の行は、コンパイラに*src/garden.rs*で見つかるコードを含めるように指示します。 +その内容は: + + +ファイル名: src/garden.rs + +```rust,noplayground,ignore +{{#rustdoc_include ../listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs}} +``` + + +この`pub mod vegetables;`は *src/garden/vegetables.rs* のコードも含めると言う意味です。 +そのコードは: + +```rust,noplayground,ignore +{{#rustdoc_include ../listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs}} +``` + + +それでは、これらのルールの詳細を知り、実際に試してみましょう! + + +### 関連するコードをモジュールにまとめる + + +*モジュール (module)* はクレート内のコードを整理し、可読性と再利用性を上げるのに役に立ちます。 +モジュール内のコードはデフォルトでは非公開なので、モジュールは要素の*プライバシー (priavacy)* の制御も可能にします。 +非公開の要素は、外部からの使用ができない内部的な実装の詳細です。 +モジュールとそれらの中の要素は公開にするかどうかを選ぶことができ、公開にすると、外部のコードがそれを使用し、それに依存できるようになります。 + 例えば、レストランの機能を提供するライブラリクレートを書いてみましょう。 -実際にレストランを実装することではなく、コードの関係性に注目したいので、関数にシグネチャをつけますが中身は空白のままにします。 +レストランの実装ではなくコードの関係性に注目したいので、関数にシグネチャをつけますが中身は空白のままにします。 -レストラン業界では、レストランの一部を *接客部門 (front of house)* といい、その他を *後方部門 (back of house)* といいます。 +レストラン業界では、レストランの一部を*接客部門 (front of house)* といい、その他を*後方部門 (back of house)* といいます。 接客部門とはお客さんがいるところです。接客係がお客様を席に案内し、給仕係が注文と支払いを受け付け、バーテンダーが飲み物を作ります。 後方部門とはシェフや料理人がキッチンで働き、皿洗い係が食器を片付け、マネージャが管理業務をする場所です。 -私達のクレートを現実のレストランと同じような構造にするために、関数をネストしたモジュールにまとめましょう。 -`restaurant`という名前の新しいライブラリを`cargo new --lib restaurant`と実行することで作成し、Listing 7-1 のコードを *src/lib.rs* に書き込み、モジュールと関数のシグネチャを定義してください。 +私達のクレートをこのような構造にするために、関数をネストしたモジュールにまとめましょう。 +`restaurant`という名前の新しいライブラリを`cargo new --lib restaurant`と実行することで作成し、リスト7-1のコードを *src/lib.rs* に書き込み、モジュールと関数のシグネチャを定義してください。 +以下が接客部門です: ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs:here}} +```rust,noplayground +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs}} ``` -Listing 7-1: `front_of_house`モジュールにその他のモジュールが含まれ、さらにそれらが関数を含んでいる +リスト7-1: `front_of_house`モジュールにその他のモジュールが含まれ、さらにそれらが関数を含んでいる -モジュールは、`mod`キーワードを書き、次にモジュールの名前(今回の場合、`front_of_house`)を指定することで定義されます。 +モジュールは、`mod`キーワードと、それに続くモジュールの名前(今回の場合、`front_of_house`)によって定義されます。 +次にモジュールの本体が波かっこの中に入ります。 モジュールの中には、今回だと`hosting`と`serving`のように、他のモジュールをおくこともできます。 -モジュールにはその他の要素の定義も置くことができます。例えば、構造体、enum、定数、トレイト、そして(Listing 7-1のように)関数です。 +モジュールにはその他の要素の定義も置くことができます。例えば、構造体、enum、定数、トレイト、そして(リスト7-1のように)関数です。 モジュールを使うことで、関連する定義を一つにまとめ、関連する理由を名前で示せます。 このコードを使うプログラマーは、定義を全部読むことなく、グループ単位でコードを読み進められるので、欲しい定義を見つけ出すのが簡単になるでしょう。 @@ -104,7 +256,7 @@ known as the *module tree*. -Listing 7-2は、Listing 7-1の構造のモジュールツリーを示しています。 +リスト7-2は、リスト7-1の構造のモジュールツリーを示しています。 ```text crate @@ -122,21 +274,20 @@ crate Listing 7-2: The module tree for the code in Listing 7-1 --> -Listing 7-2: Listing 7-1 のコードのモジュールツリー +リスト7-2: リスト7-1 のコードのモジュールツリー -このツリーを見ると、どのモジュールがどのモジュールの中にネストしているのかがわかります(例えば、`hosting`は`front_of_house`の中にネストしています)。 -また、いくつかのモジュールはお互いに *兄弟* の関係にある、つまり、同じモジュール内で定義されていることもわかります(例えば`hosting`と`serving`は`front_of_house`で定義されています)。 -他にも、家族関係の比喩を使って、モジュールAがモジュールBの中に入っている時、AはBの *子* であるといい、BはAの *親* であるといいます。 +このツリーを見ると、どのモジュールがどのモジュールの中にネストしているのかがわかります; 例えば、`hosting`は`front_of_house`の中にネストしています。 +また、いくつかのモジュールはお互いに*兄弟 (siblings)* の関係にある、つまり、同じモジュール内で定義されていることもわかります; 例えば`hosting`と`serving`は`front_of_house`で定義されている兄弟同士です。 +他にも、モジュールAがモジュールBの中に入っている時、AはBの*子 (child)* であるといい、BはAの*親 (parent)* であるといいます。 モジュールツリー全体が、暗黙のうちに作られた`crate`というモジュールの下にあることにも注目してください。 ファイルシステムの中を移動する時と同じように、Rustにモジュールツリー内の要素を見つけるためにはどこを探せばいいのか教えるためにパスを使います。 -関数を呼び出したいなら、そのパスを知っていなければなりません。 +関数を呼び出すためには、そのパスを知っていなければなりません。 -* *絶対パス* は、クレートの名前か`crate`という文字列を使うことで、クレートルートからスタートします。 -* *相対パス* は、`self`、`super`または今のモジュール内の識別子を使うことで、現在のモジュールからスタートします。 +* *絶対パス* は、クレートルートを起点とするフルパスです; + 絶対パスは、外部のクレートに属するコードに関してはそのクレート名で始まり、現在のクレートに属するコードに関してはリテラル`crate`で始まります。 +* *相対パス* は、現在のモジュールを起点とし、`self`、`super`、または今のモジュール内の識別子を使います。 -Listing 7-1の例に戻ってみましょう。 -`add_to_waitlist`関数をどうやって呼べばいいでしょうか? -すなわち、`add_to_waitlist`のパスは何でしょうか? -Listing 7-3 は、モジュールと関数をいくつか取り除いてコードをやや簡潔にしています。 -これを使って、クレートルートに定義された新しい`eat_at_restaurant`という関数から、`add_to_waitlist`関数を呼びだす2つの方法を示しましょう。 +Returning to Listing 7-1, say we want to call the `add_to_waitlist` function. +This is the same as asking: what’s the path of the `add_to_waitlist` function? +Listing 7-3 contains Listing 7-1 with some of the modules and functions +removed. +--> +リスト7-1に戻ってみて、例えば`add_to_waitlist`関数を呼びたいとしましょう。 +これはこう聞くのと同じです: `add_to_waitlist`のパスは何でしょうか? +リスト7-3は、リスト7-1からいくつかのモジュールと関数を削除したものを含んでいます。 + + +これを使って、クレートルートに定義された新しい`eat_at_restaurant`という関数から、`add_to_waitlist`関数を呼び出す2つの方法を示しましょう。 +これらのパスは正しいものですが、この例をこのままではコンパイルできなくしている問題が他に残っています。 +理由はすぐに説明します。 + + `eat_at_restaurant`関数はこのライブラリクレートの公開 (public) APIの1つなので、`pub`キーワードをつけておきます。 -`pub`については、[パスを`pub`キーワードで公開する][pub]の節でより詳しく学びます。 -この例はまだコンパイルできないことに注意してください。理由はすぐに説明します。 +`pub`については、[「パスを`pub`キーワードで公開する」][pub]の節でより詳しく学びます。 -Listing 7-3: `add_to_waitlist` 関数を絶対パスと相対パスで呼び出す +リスト7-3: `add_to_waitlist` 関数を絶対パスと相対パスで呼び出す `eat_at_restaurant`で最初に`add_to_waitlist`関数を呼び出す時、絶対パスを使っています。 `add_to_waitlist`関数は`eat_at_restaurant`と同じクレートで定義されているので、`crate`キーワードで絶対パスを始めることができます。 - - -`crate`の後は、`add_to_waitlist`にたどり着くまで、後に続くモジュールを書き込んでいます。 -同じ構造のファイルシステムを想像すれば、`/front_of_house/hosting/add_to_waitlist`とパスを指定して`add_to_waitlist`を実行していることに相当します。 +続けて、`add_to_waitlist`にたどり着くまで、後に続くモジュールを書き込んでいます。 +同じ構造のファイルシステムを想像してもよいでしょう: `/front_of_house/hosting/add_to_waitlist`とパスを指定して`add_to_waitlist`を実行していることに相当します。 `crate`という名前を使ってクレートルートからスタートするというのは、`/`を使ってファイルシステムのルートからスタートするようなものです。 `eat_at_restaurant`で2回目に`add_to_waitlist`関数を呼び出す時、相対パスを使っています。 パスは、モジュールツリーにおいて`eat_at_restaurant`と同じ階層で定義されているモジュールである`front_of_house`からスタートします。 これはファイルシステムで`front_of_house/hosting/add_to_waitlist`というパスを使っているのに相当します。 -名前から始めるのは、パスが相対パスであることを意味します。 +モジュール名から始めるのは、パスが相対パスであることを意味します。 相対パスを使うか絶対パスを使うかは、プロジェクトによって決めましょう。 要素を定義するコードを、その要素を使うコードと別々に動かすか一緒に動かすか、どちらが起こりそうかによって決めるのが良いです。 例えば、`front_of_house`モジュールと`eat_at_restaurant`関数を`customer_experience`というモジュールに移動させると、`add_to_waitlist`への絶対パスを更新しないといけませんが、相対パスは有効なままです。 しかし、`eat_at_restaurant`関数だけを`dining`というモジュールに移動させると、`add_to_waitlist`への絶対パスは同じままですが、相対パスは更新しないといけないでしょう。 -コードの定義と、その要素の呼び出しは独立に動かしそうなので、絶対パスのほうが好ましいです。 +一般論としては、コードの定義と、その要素の呼び出しは独立に動かしたいことが多いと思われるので、絶対パスのほうが好ましいです。 -では、Listing 7-3 をコンパイルしてみて、どうしてこれはまだコンパイルできないのか考えてみましょう! -エラーをListing 7-4 に示しています。 +では、リスト7-3をコンパイルしてみて、どうしてこれはまだコンパイルできないのか考えてみましょう! +エラーをリスト7-4に示しています。 ```console {{#include ../listings/ch07-managing-growing-projects/listing-07-03/output.txt}} @@ -134,16 +139,21 @@ error we get is shown in Listing 7-4. Listing 7-4: Compiler errors from building the code in Listing 7-3 --> -Listing 7-4: Listing 7-3のコードをビルドしたときのコンパイルエラー +リスト7-4: リスト7-3のコードをビルドしたときのコンパイルエラー エラーメッセージは、`hosting`は非公開 (private) だ、と言っています。 言い換えるなら、`hosting`モジュールと`add_to_waitlist`関数へのパスは正しいが、非公開な部分へのアクセスは許可されていないので、Rustがそれを使わせてくれないということです。 +Rustでは、すべての要素(関数、メソッド、構造体、enum、モジュール、そして定数)はデフォルトでは親モジュールに対して非公開です。 +関数や構造体などの要素を非公開にしたければ、モジュールの中に置いてください。 -Rustにおけるプライバシーは、「あらゆる要素(関数、メソッド、構造体、enum、モジュールおよび定数)は標準では非公開」というやり方で動いています。 親モジュールの要素は子モジュールの非公開要素を使えませんが、子モジュールの要素はその祖先モジュールの要素を使えます。 これは、子モジュールは実装の詳細を覆い隠しますが、子モジュールは自分の定義された文脈を見ることができるためです。 -レストランの喩えを続けるなら、レストランの後方部門になったつもりでプライバシーのルールを考えてみてください。レストランの顧客にはそこで何が起こっているのかは非公開ですが、そこで働くオフィスマネージャには、レストランのことは何でも見えるし何でもできるのです。 +レストランの喩えを続けるなら、レストランの後方部門になったつもりでプライバシーのルールを考えてみてください。レストランの顧客にはそこで何が起こっているのかは非公開ですが、そこを運営するオフィスマネージャには、レストランのことは何でも見えるし何でもできるのです。 Rustは、内部実装の詳細を隠すことが標準であるようにモジュールシステムを機能させることを選択しました。 こうすることで、内部のコードのどの部分が、外部のコードを壊すことなく変更できるのかを知ることができます。 -しかし、`pub`キーワードを使って要素を公開することで、子モジュールの内部部品を外部の祖先モジュールに見せることができます。 +しかし、Rustは`pub`キーワードを使って要素を公開することで、子モジュールの内部部品を外部の祖先モジュールに見せるという選択肢も与えています。 -Listing 7-4の、`hosting`モジュールが非公開だと言ってきていたエラーに戻りましょう。 -親モジュールの`eat_at_restaurant`関数が子モジュールの`add_to_waitlist`関数にアクセスできるようにしたいので、`hosting`モジュールに`pub`キーワードをつけます。Listing 7-5のようになります。 +リスト7-4の、`hosting`モジュールが非公開だと言ってきていたエラーに戻りましょう。 +親モジュールの`eat_at_restaurant`関数が子モジュールの`add_to_waitlist`関数にアクセスできるようにしたいので、`hosting`モジュールに`pub`キーワードをつけます。リスト7-5のようになります。 -Listing 7-5: `hosting` モジュールを `pub` として宣言することで`eat_at_restaurant`から使う +リスト7-5: `hosting` モジュールを `pub` として宣言することで`eat_at_restaurant`から使う -残念ながら、Listing 7-5 のコードもListing 7-6 に示されるようにエラーとなります。 +残念ながら、リスト7-5のコードもリスト7-6に示されるようにエラーとなります。 ```console {{#include ../listings/ch07-managing-growing-projects/listing-07-05/output.txt}} @@ -226,27 +233,31 @@ Listing 7-6. Listing 7-6: Compiler errors from building the code in Listing 7-5 --> -Listing 7-6: Listing 7-5 のコードをビルドしたときのコンパイルエラー +リスト7-6: リスト7-5のコードをビルドしたときのコンパイルエラー 何が起きたのでしょう?`pub`キーワードを`mod hosting`の前に追加したことで、このモジュールは公開されました。 この変更によって、`front_of_house`にアクセスできるなら、`hosting`にもアクセスできるようになりました。 しかし`hosting`の *中身* はまだ非公開です。モジュールを公開してもその中身は公開されないのです。 -モジュールに`pub`キーワードがついていても、祖先モジュールのコードはモジュールを参照できるようになるだけです。 - +モジュールに`pub`キーワードがついていても、祖先モジュールのコードはモジュールを参照できるようになるだけで、その内部のコードへのアクセスは許可されません。 +モジュールはコンテナなので、モジュールを公開しただけでは、できることはあまりありません; +さらに先へ進み、モジュール内のひとつまたは複数の要素も公開することを選択する必要があります。 -Listing 7-6 のエラーは`add_to_waitlist`関数が非公開だと言っています。 +リスト7-6のエラーは`add_to_waitlist`関数が非公開だと言っています。 プライバシーのルールは、モジュール同様、構造体、enum、関数、メソッドにも適用されるのです。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs}} ``` -Listing 7-7: `pub`キーワードを`mod hosting`と`fn add_to_waitlist`に追加することで、`eat_at_restaurant`からこの関数を呼べるようになる +リスト7-7: `pub`キーワードを`mod hosting`と`fn add_to_waitlist`に追加することで、`eat_at_restaurant`からこの関数を呼べるようになる これでこのコードはコンパイルできます! -絶対パスと相対パスをもう一度確認して、どうして`pub`キーワードを追加することで`add_to_waitlist`のそれらのパスを使えるようになるのか、プライバシールールの観点からもう一度確認してみてみましょう。 +どうして`pub`キーワードを追加することで`add_to_waitlist`のそれらのパスを使えるようになるのか、 +プライバシールールの観点から確認するために、絶対パスと相対パスを見てみましょう。 絶対パスは、クレートのモジュールツリーのルートである`crate`から始まります。 クレートルートの中に`front_of_house`が定義されています。 @@ -310,59 +322,119 @@ function call is valid! `front_of_house`モジュールは`eat_at_restaurant`と同じモジュールで定義されているので、`eat_at_restaurant`が定義されている場所からの相対パスが使えます。 そして、`hosting`と`add_to_waitlist`は`pub`が付いていますから、残りのパスについても問題はなく、この関数呼び出しは有効というわけです。 + +他のプロジェクトからあなたのコードを利用できるようにライブラリクレートを共有するつもりなら、 +公開APIは、クレート利用者があなたのコードとどう相互作用できるかを決定する、クレート利用者との契約となります。 +人々があなたのクレートに依存しやすくするためには、公開APIへの変更の管理に関する多数の考慮事項があります。 +これらの考慮事項はこの本のスコープ外です; このトピックに興味がある場合は、[The Rust API Guidelines][api-guidelines]を参照してください。 + + + +> #### バイナリとライブラリの両方を持つパッケージでのベストプラクティス +> +> パッケージは*src/main.rs*バイナリクレートルートと*src/lib.rs*ライブラリクレートルートの両方を含むことができ、 +> デフォルトでは両方のクレートがパッケージ名を持つことを説明しました。 +> 典型的には、ライブラリとバイナリのクレート両方を含むこのパターンのパッケージでは、バイナリクレートには +> ライブラリクレートのコードを呼び出して、実行可能形式を開始するために必要な最低限のコードを持たせます。 +> こうすることで、ライブラリクレートのコードは共有できるので、 +> 他のプロジェクトはこのパッケージが提供するほとんどの機能を活用することができます。 +> +> モジュールツリーは*src/lib.rs*内に定義してください。 +> その場合、バイナリクレートからは、パッケージ名でから始まるパスを使って公開された要素を使用することができます。 +> バイナリクレートは、そのライブラリクレートを利用する完全に外部のクレートとまったく同じように、 +> ライブラリクレートの利用者になります: 公開APIしか使用することができません。 +> これは良いAPIを設計する助けになります; あなたは作者であるだけでなく、利用者にもなるのです! +> +> [第12章][ch12]では、バイナリクレートとライブラリクレートの両方を含むコマンドラインプログラムを使って、 +> この整理法の実践を示します。 + ### 相対パスを`super`で始める -親モジュールから始まる相対パスなら、`super`を最初につけることで構成できます。 +現在のモジュールやクレートルートではなく、親モジュールから始まる相対パスなら、`super`を最初につけることで構成できます。 ファイルシステムパスを`..`構文で始めるのに似ています。 -どのようなときにこの機能が使いたくなるのでしょう? +`super`を使用することで、親モジュールにあることを知っている要素を参照することができます。 +これにより、そのモジュールが親と密接に関連しているが、いつか親がモジュールツリー内のどこかに移動されるかもしれないという場合に、モジュールツリーを再編成するのがより簡単になるかもしれません。 -シェフが間違った注文を修正し、自分でお客さんに持っていくという状況をモデル化している、Listing 7-8 を考えてみてください。 -`fix_incorrect_order`関数は`serve_order`関数を呼び出すために、`super`から始まる`serve_order`関数へのパスを使っています。 +シェフが間違った注文を修正し、自分でお客さんに持っていくという状況をモデル化している、リスト7-8を考えてみてください。 +`back_of_house`モジュールで定義されている`fix_incorrect_order`関数は、親モジュールで定義されている`deliver_order`関数を呼び出すために、`super`から始まる`deliver_order`関数へのパスを使っています。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs}} ``` -Listing 7-8: `super` で始まる相対パスを使って関数を呼び出す +リスト7-8: `super` で始まる相対パスを使って関数を呼び出す `fix_incorrect_order`関数は`back_of_house`モジュールの中にあるので、`super`を使って`back_of_house`の親モジュールにいけます。親モジュールは、今回の場合ルートである`crate`です。 -そこから、`serve_order`を探し、見つけ出します。 +そこから、`deliver_order`を探し、見つけ出します。 成功! -もしクレートのモジュールツリーを再編成することにした場合でも、`back_of_house`モジュールと`serve_order`関数は同じ関係性で有り続け、一緒に動くように思われます。 +もしクレートのモジュールツリーを再編成することにした場合でも、`back_of_house`モジュールと`deliver_order`関数は同じ関係性で有り続け、一緒に動くように思われます。 そのため、`super`を使うことで、将来このコードが別のモジュールに移動するとしても、更新する場所が少なくて済むようにしました。 -構造体やenumも`pub`を使って公開するよう指定できますが、追加の細目がいくつかあります。 +few details extra to the usage of `pub` with structs and enums. If we use `pub` +before a struct definition, we make the struct public, but the struct’s fields +will still be private. We can make each field public or not on a case-by-case +basis. In Listing 7-9, we’ve defined a public `back_of_house::Breakfast` struct +with a public `toast` field but a private `seasonal_fruit` field. This models +the case in a restaurant where the customer can pick the type of bread that +comes with a meal, but the chef decides which fruit accompanies the meal based +on what’s in season and in stock. The available fruit changes quickly, so +customers can’t choose the fruit or even see which fruit they’ll get. +--> +構造体やenumも`pub`を使って公開するよう指定できますが、構造体とenumでの`pub`の使用に関しては追加の細目がいくつかあります。 構造体定義の前に`pub`を使うと、構造体は公開されますが、構造体のフィールドは非公開のままなのです。 それぞれのフィールドを公開するか否かを個々に決められます。 -Listing 7-9 では、公開の`toast`フィールドと、非公開の`seasonal_fruit`フィールドをもつ公開の`back_of_house::Breakfast`構造体を定義しました。 +リスト7-9では、公開の`toast`フィールドと、非公開の`seasonal_fruit`フィールドをもつ公開の`back_of_house::Breakfast`構造体を定義しました。 これは、例えば、レストランで、お客さんが食事についてくるパンの種類は選べるけれど、食事についてくるフルーツは季節と在庫に合わせてシェフが決める、という状況をモデル化しています。 提供できるフルーツはすぐに変わるので、お客さんはフルーツを選ぶどころかどんなフルーツが提供されるのか知ることもできません。 @@ -394,7 +466,7 @@ Listing 7-9 では、公開の`toast`フィールドと、非公開の`seasonal_ --> ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs}} ``` @@ -402,7 +474,7 @@ Listing 7-9 では、公開の`toast`フィールドと、非公開の`seasonal_ Listing 7-9: A struct with some public fields and some private fields --> -Listing 7-9: 公開のフィールドと非公開のフィールドとを持つ構造体 +リスト7-9: 公開のフィールドと非公開のフィールドとを持つ構造体 一方で、enumを公開すると、そのヴァリアントはすべて公開されます。 -Listing 7-10 に示されているように、`pub`は`enum`キーワードの前にだけおけばよいのです。 +リスト7-10に示されているように、`pub`は`enum`キーワードの前にだけおけばよいのです。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-10/src/lib.rs}} ``` @@ -446,17 +518,21 @@ Listing 7-10 に示されているように、`pub`は`enum`キーワードの Listing 7-10: Designating an enum as public makes all its variants public --> -Listing 7-10: enumを公開に指定することはそのヴァリアントをすべて公開にする +リスト7-10: enumを公開に指定することはそのヴァリアントをすべて公開にする `Appetizer`というenumを公開したので、`Soup`と`Salad`というヴァリアントも`eat_at_restaurant`で使えます。 + + enumはヴァリアントが公開されてないとあまり便利ではないのですが、毎回enumのすべてのヴァリアントに`pub`をつけるのは面倒なので、enumのヴァリアントは標準で公開されるようになっているのです。 構造体はフィールドが公開されていなくても便利なことが多いので、構造体のフィールドは、`pub`がついてない限り標準で非公開という通常のルールに従うわけです。 @@ -468,4 +544,11 @@ first, and then we’ll show how to combine `pub` and `use`. まだ勉強していない、`pub`の関わるシチュエーションがもう一つあります。モジュールシステムの最後の機能、`use`キーワードです。 `use`自体の勉強をした後、`pub`と`use`を組み合わせる方法についてお見せします。 -[pub]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#%E3%83%91%E3%82%B9%E3%82%92pub%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E3%81%A7%E5%85%AC%E9%96%8B%E3%81%99%E3%82%8B + +[pub]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#パスをpubキーワードで公開する +[api-guidelines]: https://rust-lang.github.io/api-guidelines/ +[ch12]: ch12-00-an-io-project.html diff --git a/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md b/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md index 3048b18a5..c18f17263 100644 --- a/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md +++ b/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md @@ -4,18 +4,17 @@ ## `use`キーワードでパスをスコープに持ち込む -これまで関数呼び出しのために書いてきたパスは、長く、繰り返しも多くて不便なものでした。 -例えば、Listing 7-7 においては、絶対パスを使うか相対パスを使うかにかかわらず、`add_to_waitlist`関数を呼ぼうと思うたびに`front_of_house`と`hosting`も指定しないといけませんでした。 -ありがたいことに、この手続きを簡単化する方法があります。 -`use`キーワードを使うことで、パスを一度スコープに持ち込んでしまえば、それ以降はパス内の要素がローカルにあるかのように呼び出すことができるのです。 +関数を呼び出すためにパスを略さずに書かなくてはならないのは、繰り返しも多くて不便に感じられるでしょう。 +リスト7-7においては、絶対パスを使うか相対パスを使うかにかかわらず、`add_to_waitlist`関数を呼ぼうと思うたびに`front_of_house`と`hosting`も指定しないといけませんでした。 +ありがたいことに、この手続きを簡単化する方法があります: +一度`use`キーワードを使ってショートカットを作成すれば、そのスコープ内であればどこでも、より短い名前を使用できます。 -Listing 7-11 では、`crate::front_of_house::hosting`モジュールを`eat_at_restaurant`関数のスコープに持ち込むことで、`eat_at_restaurant`において、`hosting::add_to_waitlist`と指定するだけで`add_to_waitlist`関数を呼び出せるようにしています。 +リスト7-11では、`crate::front_of_house::hosting`モジュールを`eat_at_restaurant`関数のスコープに持ち込むことで、`eat_at_restaurant`において、`hosting::add_to_waitlist`と指定するだけで`add_to_waitlist`関数を呼び出せるようにしています。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs}} ``` -Listing 7-11: `use` でモジュールをスコープに持ち込む +リスト7-11: `use` でモジュールをスコープに持ち込む -`use`と相対パスで要素をスコープに持ち込むこともできます。 -Listing 7-12 はListing 7-11 と同じふるまいを得るためにどう相対パスを書けば良いかを示しています。 +`use`は、`use`が出現した特定のスコープでのみ使えるショートカットを作成することに注意してください。 +リスト7-12は`eat_at_restaurant`関数を新しい子モジュール`customer`の中に移動していますが、このモジュールは`use`文とは異なるスコープなので、この関数本体はコンパイルできないでしょう: ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs:here}} +```rust,noplayground,test_harness,does_not_compile,ignore +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs}} +``` + + +リスト7-12: `use`文はそれが属するスコープ内にのみ適用される + + +コンパイルエラーは`customer`モジュール内ではショートカットが適用されないことを示しています: + +```console +{{#include ../listings/ch07-managing-growing-projects/listing-07-12/output.txt}} ``` -Listing 7-12: モジュールを`use`と相対パスを使ってスコープに持ち込む +`use`がそのスコープ内で使用されていないという警告も出ていることに気づくでしょう! +この問題を修正するには、`use`も`customer`モジュールの中に移動するか、`customer`子モジュールの中で`super::hosting`によって親モジュールにあるショートカットを参照してください。 -Listing 7-11 を見て、なぜ`use crate::front_of_house::hosting`と書いて`eat_at_restaurant`内で`hosting::add_to_waitlist`と呼び出したのか不思議に思っているかもしれません。Listing 7-13 のように、`use`で`add_to_waitlist`までのパスをすべて指定しても同じ結果が得られるのに、と。 +リスト7-11を見て、なぜ`use crate::front_of_house::hosting`と書いて`eat_at_restaurant`内で`hosting::add_to_waitlist`と呼び出したのか不思議に思っているかもしれません。リスト7-13のように、`use`で`add_to_waitlist`までのパスをすべて指定しても同じ結果が得られるのに、と。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs}} ``` -Listing 7-13: `add_to_waitlist` 関数を`use` でスコープに持ち込む。このやりかたは慣例的ではない +リスト7-13: `add_to_waitlist` 関数を`use` でスコープに持ち込む。このやりかたは慣例的ではない -Listing 7-11 も 7-13 もおなじ仕事をしてくれますが、関数をスコープに`use`で持ち込む場合、Listing 7-11 のほうが慣例的なやり方です。 -関数の親モジュールを`use`で持ち込むことで、関数を呼び出す際、毎回親モジュールを指定しなければならないようにすれば、フルパスを繰り返して書くことを抑えつつ、関数がローカルで定義されていないことを明らかにできます。 -Listing 7-13 のコードではどこで`add_to_waitlist`が定義されたのかが不明瞭です。 +リスト7-11も7-13もおなじ仕事をしてくれますが、関数をスコープに`use`で持ち込む場合、リスト7-11のほうが慣例的なやり方です。 +関数の親モジュールを`use`で持ち込むということは、関数を呼び出す際、毎回親モジュールを指定しなければならないということです。 +関数を呼び出すときに親モジュールを指定することで、フルパスを繰り返して書くことを抑えつつ、関数がローカルで定義されていないことを明らかにできます。 +リスト7-13のコードではどこで`add_to_waitlist`が定義されたのかが不明瞭です。 一方で、構造体やenumその他の要素を`use`で持ち込むときは、フルパスを書くのが慣例的です。 -Listing 7-14 は標準ライブラリの`HashMap`構造体をバイナリクレートのスコープに持ち込む慣例的なやり方を示しています。 +リスト7-14は標準ライブラリの`HashMap`構造体をバイナリクレートのスコープに持ち込む慣例的なやり方を示しています。 -Listing 7-14: `HashMap`を慣例的なやり方でスコープに持ち込む +リスト7-14: `HashMap`を慣例的なやり方でスコープに持ち込む 同じ名前の2つの要素を`use`でスコープに持ち込むのはRustでは許されないので、そのときこの慣例は例外的に不可能です。 -Listing 7-15は、同じ名前を持つけれど異なる親モジュールを持つ2つの`Result`型をスコープに持ち込み、それらを参照するやり方を示しています。 +リスト7-15は、同じ名前を持つけれど異なる親モジュールを持つ2つの`Result`型をスコープに持ち込み、それらを参照するやり方を示しています。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-15/src/lib.rs:here}} ``` @@ -167,7 +188,7 @@ Listing 7-15は、同じ名前を持つけれど異なる親モジュールを Listing 7-15: Bringing two types with the same name into the same scope requires using their parent modules. --> -Listing 7-15: 同じ名前を持つ2つの型を同じスコープに持ち込むには親モジュールを使わないといけない。 +リスト7-15: 同じ名前を持つ2つの型を同じスコープに持ち込むには親モジュールを使わないといけない。 -同じ名前の2つの型を`use`を使って同じスコープに持ち込むという問題には、もう一つ解決策があります。パスの後に、`as`と型の新しいローカル名、即ちエイリアスを指定すればよいのです。 -Listing 7-16 は、Listing 7-15 のコードを、2つの`Result`型のうち一つを`as`を使ってリネームするという別のやり方で書いたものを表しています。 +同じ名前の2つの型を`use`を使って同じスコープに持ち込むという問題には、もう一つ解決策があります。パスの後に、`as`と型の新しいローカル名、即ち*エイリアス*を指定すればよいのです。 +リスト7-16は、リスト7-15のコードを、2つの`Result`型のうち一つを`as`を使ってリネームするという別のやり方で書いたものを表しています。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-16/src/lib.rs:here}} ``` @@ -205,7 +226,7 @@ Listing 7-16 は、Listing 7-15 のコードを、2つの`Result`型のうち一 Listing 7-16: Renaming a type when it’s brought into scope with the `as` keyword --> -Listing 7-16: 型がスコープに持ち込まれた時、`as`キーワードを使ってその名前を変えている +リスト7-16: 型がスコープに持ち込まれた時、`as`キーワードを使ってその名前を変えている 2つめの`use`文では、`std::io::Result`に、`IoResult`という新たな名前を選んでやります。`std::fmt`の`Result`もスコープに持ち込んでいますが、この名前はこれとは衝突しません。 -Listing 7-15もListing 7-16も慣例的とみなされているので、どちらを使っても構いませんよ! +リスト7-15もリスト7-16も慣例的とみなされているので、どちらを使っても構いませんよ! -Listing 7-17 は Listing 7-11 のコードのルートモジュールでの`use`を`pub use`に変更したものを示しています。 +リスト7-17はリスト7-11のコードのルートモジュールでの`use`を`pub use`に変更したものを示しています。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs}} ``` -Listing 7-17: `pub use`で、新たなスコープのコードがその名前を使えるようにする +リスト7-17: `pub use`で、新たなスコープのコードがその名前を使えるようにする -`pub use`を使うことで、外部のコードが`hosting::add_to_waitlist`を使って`add_to_waitlist`関数を呼び出せるようになりました。 -`pub use`を使っていなければ、`eat_at_restaurant`関数は`hosting::add_to_waitlist`を自らのスコープ内で使えるものの、外部のコードはこの新しいパスを利用することはできないでしょう。 +この変更を行う前の状態では、外部のコードはパス`restaurant::front_of_house::hosting::add_to_waitlist()`を使用して`add_to_wishlist`関数を呼ばなくてはなりませんでした。 +この`pub use`によってルートモジュールから`hosting`モジュールを再公開された今、外部のコードはパス`restaurant::hosting::add_to_waitlist()`を使用できるようになりました。 再公開は、あなたのコードの内部構造と、あなたのコードを呼び出すプログラマーたちのその領域に関しての見方が異なるときに有用です。 例えば、レストランの比喩では、レストランを経営している人は「接客部門 (front of house)」と「後方部門 (back of house)」のことについて考えるでしょう。 しかし、レストランを訪れるお客さんは、そのような観点からレストランの部門について考えることはありません。 `pub use`を使うことで、ある構造でコードを書きつつも、別の構造で公開するということが可能になります。 こうすることで、私達のライブラリを、ライブラリを開発するプログラマにとっても、ライブラリを呼び出すプログラマにとっても、よく整理されたものとすることができます。 +第14章の[「`pub use`で便利な公開APIをエクスポートする」][ch14-pub-use]の節で、`pub use`の別の例と、それがクレートのドキュメンテーションにどう影響するかを見ることにしましょう。 -標準ライブラリ (`std`) も、私達のパッケージの外部にあるクレートだということに注意してください。 +標準`std`ライブラリも、私達のパッケージの外部にあるクレートだということに注意してください。 標準ライブラリはRust言語に同梱されているので、 *Cargo.toml* を `std`を含むように変更する必要はありません。 しかし、その要素をそこから私達のパッケージのスコープに持ち込むためには、`use`を使って参照する必要はあります。 例えば、`HashMap`には次の行を使います。 @@ -370,7 +396,7 @@ files. For example, these two `use` statements we had in the Guessing Game in Listing 2-4 bring items from `std` into scope: --> 同じクレートか同じモジュールで定義された複数の要素を使おうとする時、それぞれの要素を一行一行並べると、縦に大量のスペースを取ってしまいます。 -例えば、Listing 2-4の数当てゲームで使った次の2つの`use`文が`std`からスコープへ要素を持ち込みました。 +例えば、リスト2-4の数当てゲームで使った次の2つの`use`文が`std`からスコープへ要素を持ち込みました。 代わりに、ネストしたパスを使うことで、同じ一連の要素を1行でスコープに持ち込めます。 -これをするには、Listing 7-18 に示されるように、パスの共通部分を書き、2つのコロンを続け、そこで波括弧で互いに異なる部分のパスのリストを囲みます。 +これをするには、リスト7-18に示されるように、パスの共通部分を書き、2つのコロンを続け、そこで波括弧で互いに異なる部分のパスのリストを囲みます。 -Listing 7-18: 同じプレフィックスをもつ複数の要素をスコープに持ち込むためにネストしたパスを指定する +リスト7-18: 同じプレフィックスをもつ複数の要素をスコープに持ち込むためにネストしたパスを指定する ネストしたパスはパスのどの階層においても使うことができます。これはサブパスを共有する2つの`use`文を合体させるときに有用です。 -例えば、Listing 7-19 は2つの`use`文を示しています:1つは`std::io`をスコープに持ち込み、もう一つは`std::io::Write`をスコープに持ち込んでいます。 +例えば、リスト7-19は2つの`use`文を示しています:1つは`std::io`をスコープに持ち込み、もう一つは`std::io::Write`をスコープに持ち込んでいます。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-19/src/lib.rs}} ``` @@ -434,21 +460,21 @@ two `use` statements that share a subpath. For example, Listing 7-19 shows two Listing 7-19: Two `use` statements where one is a subpath of the other --> -Listing 7-19: 片方がもう片方のサブパスである2つの`use`文 +リスト7-19: 片方がもう片方のサブパスである2つの`use`文 -これらの2つのパスの共通部分は`std::io`であり、そしてこれは最初のパスにほかなりません。これらの2つのパスを1つの`use`文へと合体させるには、Listing 7-20 に示されるように、ネストしたパスに`self`を使いましょう。 +これらの2つのパスの共通部分は`std::io`であり、そしてこれは最初のパスにほかなりません。これらの2つのパスを1つの`use`文へと合体させるには、リスト7-20に示されるように、ネストしたパスに`self`を使いましょう。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-20/src/lib.rs}} ``` @@ -456,7 +482,7 @@ the nested path, as shown in Listing 7-20. Listing 7-20: Combining the paths in Listing 7-19 into one `use` statement --> -Listing 7-20: Listing 7-19 のパスを一つの `use` 文に合体させる +リスト7-20: リスト7-19のパスを一つの `use` 文に合体させる パスにおいて定義されているすべての公開要素をスコープに持ち込みたいときは、glob演算子 `*` をそのパスの後ろに続けて書きましょう: @@ -499,5 +525,11 @@ for more information on that pattern. glob演算子はしばしば、テストの際、テストされるあらゆるものを`tests`モジュールに持ち込むために使われます。これについては11章[テストの書き方][writing-tests]の節で話します。 glob演算子はプレリュードパターンの一部としても使われることがあります:そのようなパターンについて、より詳しくは[標準ライブラリのドキュメント](https://doc.rust-lang.org/std/prelude/index.html#other-preludes)をご覧ください。 + +[ch14-pub-use]: ch14-02-publishing-to-crates-io.html#pub-useで便利な公開apiをエクスポートする [rand]: ch02-00-guessing-game-tutorial.html#乱数を生成する [writing-tests]: ch11-01-writing-tests.html#テストの記述法 diff --git a/src/ch07-05-separating-modules-into-different-files.md b/src/ch07-05-separating-modules-into-different-files.md index 2c45efc91..099d05888 100644 --- a/src/ch07-05-separating-modules-into-different-files.md +++ b/src/ch07-05-separating-modules-into-different-files.md @@ -12,21 +12,33 @@ file to make the code easier to navigate. モジュールが大きくなる時、コードを読み進めやすくするため、それらの定義を別のファイルへ移動させたくなるかもしれません。 -例えば、Listing 7-17 のコードからはじめましょう。クレートルートのファイルをListing 7-21 のコードを持つように変更して、`front_of_house`モジュールをそれ専用のファイル`src/front_of_house.rs`に動かしましょう。 +For example, let’s start from the code in Listing 7-17 that had multiple +restaurant modules. We’ll extract modules into files instead of having all the +modules defined in the crate root file. In this case, the crate root file is +*src/lib.rs*, but this procedure also works with binary crates whose crate root +file is *src/main.rs*. +--> +例として、複数のレストランモジュールを持つリスト7-17のコードからはじめましょう。 +すべてのモジュールをクレートルートファイルで定義するのをやめて、複数のファイルにモジュールを抽出することにします。 今回、クレートルートファイルは`src/lib.rs`ですが、この手続きはクレートルートファイルが`src/main.rs`であるバイナリクレートでもうまく行きます。 + +まず、`front_of_house`モジュールをそれ専用のファイルに抽出しましょう。 +`front_of_house`モジュールの波かっこの中のコードを削除し、`mod front_of_house;`宣言だけを残して、 *src/lib.rs* がリスト7-21に示すコードを含むようにしてください。 +リスト7-22で *src/front_of_house.rs* ファイルを作成するまで、このコードはコンパイルできないことに注意してください。 + ファイル名: src/lib.rs -```rust,ignore +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs}} ``` @@ -34,13 +46,16 @@ crates whose crate root file is *src/main.rs*. Listing 7-21: Declaring the `front_of_house` module whose body will be in *src/front_of_house.rs* --> -Listing 7-21: `front_of_house`モジュールを宣言する。その中身は`src/front_of_house.rs`内にある +リスト7-21: `front_of_house`モジュールを宣言する。その中身は`src/front_of_house.rs`内にある -そして、 Listing 7-22 のように、*src/front_of_house.rs* には`front_of_house` モジュールの中身の定義を与えます。 +次に リスト7-22に示すように、*src/front_of_house.rs* という名前の新しいファイルに、波かっこの中にあったコードを配置してください。 +コンパイラは、クレートルートで`front_of_house`という名前のモジュール宣言を見つけたときは、このファイルを探せばいいということを知っています。 -Listing 7-22: *src/front_of_house.rs*における、`front_of_house`モジュール内部の定義 +リスト7-22: *src/front_of_house.rs*における、`front_of_house`モジュール内部の定義 + + +`mod`宣言を使用したファイルのロードは、モジュールツリー内で*一回*のみ行う必要があることに注意してください。 +一度コンパイラが、そのファイルがプロジェクトの一部であることを認識したら(そして、`mod`文を書いた場所に応じてモジュールツリー内のどこにコードがあることになるかを認識したら)、[「モジュールツリーの要素を示すためのパス」][paths]節で扱ったように、プロジェクト内の他のファイルは、モジュールが宣言された場所へのパスを使用してロードされたファイルのコードを参照するべきです。 +別の言い方をすれば、`mod`は他のプログラミング言語で見られるような“include”操作では*ありません*。 + + +つづけて`hosting`モジュールをそれ専用のファイルに抽出します。 +`hosting`はルートモジュールの子ではなく`front_of_house`の子モジュールなので、このプロセスは少し異なります。 +`hosting`のためのファイルを、モジュールツリー上での祖先に対応して名付けられた新しいディレクトリ(今回の場合は *src/front_of_house/*)内に配置しましょう。 -`mod front_of_house`の後にブロックではなくセミコロンを使うと、Rustにモジュールの中身をモジュールと同じ名前をした別のファイルから読み込むように命令します。 -私達の例で、つづけて`hosting`モジュールをそれ専用のファイルに抽出するには、`src/front_of_house.rs`が`hosting`モジュールの宣言のみを含むように変更します: +`hosting`の移動を開始するために、`src/front_of_house.rs`が`hosting`モジュールの宣言のみを含むように変更します: -さらに*src/front_of_house* ディレクトリと*src/front_of_house/hosting.rs* ファイルを作って、`hosting`モジュール内でなされていた定義を持つようにします。 +さらに*src/front_of_house* ディレクトリと*hosting.rs* ファイルを作って、`hosting`モジュール内でなされていた定義を持つようにします。 ファイル名: src/front_of_house/hosting.rs -```rust +```rust,ignore {{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house/hosting.rs}} ``` -定義は別のファイルにあるにもかかわらず、モジュールツリーは同じままであり、`eat_at_restaurant`内での関数呼び出しもなんの変更もなくうまく行きます。 +If we instead put *hosting.rs* in the *src* directory, the compiler would +expect the *hosting.rs* code to be in a `hosting` module declared in the crate +root, and not declared as a child of the `front_of_house` module. The +compiler’s rules for which files to check for which modules’ code means the +directories and files more closely match the module tree. +--> +もし*src*ディレクトリ内に*hosting.rs*を置いた場合は、コンパイラは*hosting.rs*のコードは`front_of_house`モジュールの子としてではなく、クレートルート内で宣言された`hosting`モジュールにあると期待するでしょう。 +コンパイラがどのモジュールのコードのためにどのファイルをチェックするかの規則は、ディレクトリとファイルがモジュールツリーと密接に一致することを意味します。 + + +> ### 別のファイルパス +> +> ここまでRustコンパイラが使用するもっとも慣例的なファイルパスについて扱ってきましたが、Rustは古いスタイルのファイルパスもサポートしています。 +> クレートルート内で宣言された`front_of_house`という名前のモジュールに対して、コンパイラは以下の場所からコードを探します: +> +> * *src/front_of_house.rs* (ここまで扱ってきたもの) +> * *src/front_of_house/mod.rs* (古いスタイルの、今もサポートされているパス) +> +> `front_of_house`のサブモジュールである、`hosting`という名前のモジュールに対しては、コンパイラは以下の場所からコードを探します: +> +> * *src/front_of_house/hosting.rs* (ここまで扱ってきたもの) +> * *src/front_of_house/hosting/mod.rs* (古いスタイルの、今もサポートされているパス) +> +> 同一のモジュールに対して両方のスタイルを使用するとコンパイルエラーになります。 +> 異なるモジュールに対して両方のスタイルを混ぜて使用することは許可されていますが、プロジェクトを見て回る人たちにとって混乱を招くかもしれません。 +> +> *mod.rs* という名前のファイルを使用するスタイルの主な欠点は、プロジェクト内に *mod.rs* という名前のファイルが大量にできることになり、エディタで同時に開いたときに混乱を招きやすいことです。 + + +各モジュールのコードを独立したファイルに移動しましたが、モジュールツリーは同じままです。 +定義が別のファイルにあるにもかかわらず、`eat_at_restaurant`内での関数呼び出しもなんの変更もなくうまく行きます。 このテクニックのおかげで、モジュールが大きくなってきた段階で新しいファイルへ動かす、ということができます。 次の章では、きちんと整理されたあなたのコードで使うことができる、標準ライブラリのいくつかのコレクションデータ構造を見ていきます。 + +[paths]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html diff --git a/src/ch08-00-common-collections.md b/src/ch08-00-common-collections.md index e90c5ffcf..9bd408a74 100644 --- a/src/ch08-00-common-collections.md +++ b/src/ch08-00-common-collections.md @@ -24,11 +24,11 @@ Rustの標準ライブラリは、*コレクション*と呼ばれる多くの Rustのプログラムにおいて、非常に頻繁に使用される3つのコレクションについて議論しましょう。 * *ベクタ型*は、可変長の値を並べて保持できる。 @@ -45,11 +45,11 @@ see [the documentation][collections]. 標準ライブラリで提供されている他の種のコレクションについて学ぶには、 [ドキュメント][collections]を参照されたし。 -[collections]: https://doc.rust-lang.org/std/collections/index.html - ベクタ型、文字列、ハッシュマップの生成と更新方法や、各々が特別な点について議論していきましょう。 + +[collections]: https://doc.rust-lang.org/std/collections/index.html diff --git a/src/ch08-01-vectors.md b/src/ch08-01-vectors.md index ed7d41633..57ee7a6c2 100644 --- a/src/ch08-01-vectors.md +++ b/src/ch08-01-vectors.md @@ -12,11 +12,10 @@ of the same type. They are useful when you have a list of items, such as the lines of text in a file or the prices of items in a shopping cart. --> -最初に見るコレクション型は`Vec`であり、これは*ベクタ*としても知られています。 -ベクタは単体のデータ構造でありながら複数の値を保持でき、それらの値をメモリ上に隣り合わせに並べます。 -ベクタには同じ型の値しか保持できません。 -要素のリストがある場合にベクタは有用です。 -例えば、テキストファイルの各行とか、ショッピングカートのアイテムの価格などです。 +最初に見るコレクション型は`Vec`です。*ベクタ*とも呼ばれます。 +ベクタを使用することで、複数の値をメモリ上で互いに隣り合うように単一のデータ構造に保持することができます。 +ベクタは同じ型の値のみ保持することができます。 +テキストファイルの各行や、ショッピングカートのアイテムの価格などのような、要素のリストがある場合にベクタは有用です。 -空のベクタを新たに作るには、リスト8-1に示すように`Vec::new`関数を呼びます。 +空のベクタを新たに作成するには、リスト8-1に示すように`Vec::new`関数を呼びます。 ```rust {{#rustdoc_include ../listings/ch08-common-collections/listing-08-01/src/main.rs:here}} @@ -40,44 +39,42 @@ Listing 8-1. of type `i32` --> -リスト8-1:新しい空のベクタを生成して`i32`型の値を保持する +リスト8-1:`i32`型の値を保持する新しい空のベクタを作成する -ここで、型注釈を付けていることに注目してください。 -なぜなら、このベクタに対して何も値を挿入していないので、コンパイラには私たちがどんなデータを保持させるつもりか推測できないからです。 +ここで型注釈を付けていることに注目してください。 +このベクタには何も値を挿入していないので、コンパイラには私たちがどんなデータを保持させるつもりか分かりません。 これは重要な点です。 -ベクタはジェネリクスを使用して実装されています。 -あなた自身の型でどうジェネリクスを使用するかついては第10章で解説します。 -現時点では標準ライブラリで提供される`Vec`型は、どんな型でも保持でき、ある特定のベクタがある型を保持するとき、その型は山かっこ内に指定されることを知っておいてください。 -リスト8-1では、コンパイラに`v`の`Vec`は`i32`型の要素を保持すると指示しました。 +ベクタはジェネリクスを使用して実装されています; ジェネリクスを使用する自身の型をどう使用するかついては第10章で解説します。 +今のところは、標準ライブラリで提供される`Vec`型は、どんな型でも保持できると理解しておいてください。 +特定の型を保持するベクタを作成するときには、その型を山かっこ内に指定すればよいです。 +リスト8-1では、コンパイラに`v`の`Vec`は`i32`型の要素を保持すると指示していたのです。 -いったん値を挿入すると、多くの場合、コンパイラは保持させたい値の型を推論できるようになります。 -ですから、より現実的なコードでは、型注釈を付ける必要はあまりないでしょう。 -また、初期値を持つ`Vec`を生成する方が一般的ですし、Rustには`vec!`という便利なマクロも用意されています。 -このマクロは与えた値を保持する新しいベクタを生成します。 -リスト8-2では、`1`、`2`、`3`という値を持つ新しい`Vec`を生成しています。 -整数型を`i32`にしているのは、3章の[「データ型」][data-types]節で学んだように、これが標準の整数型だからです。 +`Vec`を作成する場合は初期値を持たせることのほうが多いでしょう。 +その場合コンパイラは保持したい値の型を推論するでしょうから、このように型注釈を付ける必要はほとんどありません。 +Rustには`vec!`という便利なマクロが用意されていて、これは与えた値を保持する新しいベクタを作成します。 +リスト8-2では、`1`、`2`、`3`という値を持つ新しい`Vec`を作成しています。 +整数の型が`i32`になっているのは、3章の[「データ型」][data-types]節で学んだように、これがデフォルトの整数型だからです。 ```rust {{#rustdoc_include ../listings/ch08-common-collections/listing-08-02/src/main.rs:here}} @@ -88,7 +85,7 @@ section of Chapter 3. values --> -リスト8-2: 値を含む新しいベクタを生成する +リスト8-2: 値を含む新しいベクタを作成する -ベクタを生成し、それから要素を追加するには、リスト8-3に示すように`push`メソッドを使います。 +ベクタを作成し、それから要素を追加するには、リスト8-3に示すように`push`メソッドを使います。 ```rust {{#rustdoc_include ../listings/ch08-common-collections/listing-08-03/src/main.rs:here}} @@ -133,43 +130,6 @@ we don’t need the `Vec` annotation. 第3章で説明したとおり、どんな変数でも、その値を変更したかったら`mut`キーワードで可変にする必要があります。 中に配置する数値は全て`i32`型であり、Rustはこのことをデータから推論するので、`Vec`という注釈は不要です。 - - -### ベクタをドロップすれば、要素もドロップする - - - -他のあらゆる`struct`(構造体)と同様に、ベクタもスコープを抜ければ解放されます。 -その様子をリスト8-4に示します。 - -```rust -{{#rustdoc_include ../listings/ch08-common-collections/listing-08-04/src/main.rs:here}} -``` - - - -リスト8-4:ベクタとその要素がドロップされる箇所を示す - - - -ベクタがドロップされると、その中身もドロップされます。 -つまり、保持されていた整数値が片付けられるということです。 -これは一見単純そうですが、ベクタの要素に対する参照を使い始めると少し複雑になり得ます。 -次はそれに挑戦しましょう! - @@ -177,69 +137,67 @@ introduce references to the elements of the vector. Let’s tackle that next! ### ベクタの要素を読む -ベクタを生成し、更新し、破棄する方法がわかったので、次のステップでは中身を読む方法について学ぶのが良いでしょう。 -ベクタに保持された値を参照する方法は2つあります。 +ベクタに保持された値を参照する方法は2つあります: 添え字を使用する方法と、`get`メソッドを使用する方法です。 これから示す例では、理解を助けるために、それらの関数からの戻り値型を注釈しています。 リスト8-5はベクタの値にアクセスする両方の方法として、添え字記法と`get`メソッドが示されています。 ```rust -{{#rustdoc_include ../listings/ch08-common-collections/listing-08-05/src/main.rs:here}} +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-04/src/main.rs:here}} ``` -リスト8-5:添え字記法か`get`メソッドを使用してベクタの要素にアクセスする +リスト8-4:添え字記法か`get`メソッドを使用してベクタの要素にアクセスする -ここでは2つのことに注目してください。 -1つ目は、3番目の要素を得るのに`2`という添え字の値を使用していることです。 -ベクタは番号で索引化されますが、その番号は0から始まります。 -2つ目は、3番目の要素を得る2つの方法とは、`&`と`[]`を使用して参照を得るものと、`get`メソッドに引数として添え字を渡して`Option<&T>`を得るものだということです。 +ここでいくつか注意があります。 +ベクタは0から始まる番号で添え字アクセスされるので、3番目の要素を得るのに`2`という添え字の値を使用しています。 +`&`と`[]`を使用することで、その添え字の値にある要素への参照が得られます。 +`get`メソッドに引数として添え字を渡して使用すると、`Option<&T>`が得られ、これは`match`で使用することができます。 -Rustのベクタには要素を参照する方法が2通りあるので、ベクタに含まれない要素の添え字を使おうとしたときのプログラムの振る舞いを選択できます。 -例として、ベクタに5つ要素があるとして、添え字100の要素にアクセスを試みた場合、プログラムがどうなるのか確認しましょう。 -リスト8-6に示します。 +Rustが要素を参照するためにこれらの2通りの方法を提供している理由は、存在する要素の範囲外の添え字の値を使おうとしたときのプログラムの振る舞いを選択できるようにするためです。 +例として、5要素のベクタがあるとして、それぞれの手法で添え字100の要素にアクセスを試みた場合、何が起こるのか確認しましょう。 +リスト8-5に示します。 ```rust,should_panic,panics -{{#rustdoc_include ../listings/ch08-common-collections/listing-08-06/src/main.rs:here}} +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-05/src/main.rs:here}} ``` -リスト8-6:5つの要素を含むベクタの添え字100の要素にアクセスしようとする +リスト8-5:5つの要素を含むベクタの添え字100の要素にアクセスしようとする `get`メソッドにベクタ外の添え字を渡すと、パニックすることなく`None`を返します。 @@ -276,27 +235,28 @@ When the program has a valid reference, the borrow checker enforces the ownership and borrowing rules (covered in Chapter 4) to ensure this reference and any other references to the contents of the vector remain valid. Recall the rule that states you can’t have mutable and immutable references in the same -scope. That rule applies in Listing 8-7, where we hold an immutable reference to -the first element in a vector and try to add an element to the end, which won’t -work if we also try to refer to that element later in the function: +scope. That rule applies in Listing 8-6, where we hold an immutable reference +to the first element in a vector and try to add an element to the end. This +program won’t work if we also try to refer to that element later in the +function: --> プログラムに有効な参照がある場合、借用チェッカー (borrow checker) は、(第4章で解説しましたが)所有権と借用規則を強制し、ベクタの中身へのこの参照や他のいかなる参照も有効であり続けることを保証してくれます。 同一スコープ上では、可変と不変な参照を同時には存在させられないというルールを思い出してください。 -このルールはリスト8-7でも適用されています。 -リスト8-7ではベクタの最初の要素への不変参照を保持しつつ、終端に要素を追加しようとしています。 -関数内のここ以降で、この要素(訳注:`first`のこと)を参照しようとすると失敗します。 +このルールはリスト8-6でも適用されています。 +リスト8-6ではベクタの最初の要素への不変参照を保持しつつ、終端に要素を追加しようとしています。 +このプログラムは、関数内のここ以降で、この要素(訳注:`first`のこと)を参照しようとすると失敗します。 ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch08-common-collections/listing-08-07/src/main.rs:here}} +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-06/src/main.rs:here}} ``` -リスト8-7:要素への参照を保持しつつ、ベクタに要素を追加しようとする +リスト8-6:要素への参照を保持しつつ、ベクタに要素を追加しようとする -リスト8-7のコードは、一見動きそうに見えるかもしれません。 +リスト8-6のコードは、一見動きそうに見えるかもしれません。 なぜ最初の要素への参照が、ベクタの終端への変更を気にかける必要があるのでしょうか? -このエラーはベクタが動作するしくみによるものです。 -新たな要素をベクタの終端に追加するとき、いまベクタのある場所に全要素を隣り合わせに配置するだけのスペースがないなら、新しいメモリを割り当て、古い要素を新しいスペースにコピーする必要があります。 +このエラーはベクタが動作するしくみによるものです: +ベクタはメモリ上に値同士を隣り合うように配置するため、新たな要素をベクタの終端に追加するとき、いまベクタが置かれている場所に全要素を隣り合わせに配置するだけのスペースがないなら、新しいメモリを割り当て、古い要素を新しいスペースにコピーする必要があります。 その場合、最初の要素を指す参照は、解放されたメモリを指すことになるでしょう。 借用規則がそのような状況に陥らないよう防いでくれるのです。 @@ -342,29 +303,29 @@ programs from ending up in that situation. ### ベクタ内の値を順に処理する -ベクタの要素に順番にアクセスしたいなら、添え字で1要素ごとにアクセスするのではなく、全要素を走査することができます。 -リスト8-8で`for`ループを使い、`i32`のベクタの各要素に対する不変な参照を得て、それらを表示する方法を示します。 +ベクタの要素に順番にアクセスするには、添え字で1要素ごとにアクセスするのではなく、全要素を走査することになるでしょう。 +リスト8-7で`for`ループを使い、`i32`のベクタの各要素に対する不変な参照を得て、それらを表示する方法を示します。 ```rust -{{#rustdoc_include ../listings/ch08-common-collections/listing-08-08/src/main.rs:here}} +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-07/src/main.rs:here}} ``` -リスト8-8:`for`ループで要素を走査し、ベクタの各要素を表示する +リスト8-7:`for`ループで要素を走査し、ベクタの各要素を表示する @@ -372,27 +333,40 @@ will add `50` to each element. リスト8-9の`for`ループでは各要素に`50`を足しています。 ```rust -{{#rustdoc_include ../listings/ch08-common-collections/listing-08-09/src/main.rs:here}} +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-08/src/main.rs:here}} ``` -リスト8-9:ベクタの要素への可変な参照を走査する +リスト8-8:ベクタの要素への可変な参照を走査する -可変参照が参照している値を変更するには、`+=`演算子を使用する前に、参照外し演算子(`*`)を使用して`i`の値にたどり着かないといけません。 +可変参照が参照している値を変更するには、`+=`演算子を使用する前に、`*`参照外し演算子を使用して`i`の値にたどり着かないといけません。 参照外し演算子については、第15章の[「参照外し演算子で値までポインタを追いかける」][deref]節でより詳しく扱います。 + + +借用チェッカーの規則のおかげで、ベクタを走査するのは不変であっても可変であっても安全です。 +もしリスト8-7やリスト8-8の`for`ループ本体の中で要素を挿入または削除しようとすると、リスト8-6のコードで発生したのと同じようなコンパイルエラーになるでしょう。 +`for`ループがベクタへの参照をつかんでいるために、それと同時にベクタ全体の変更が起こらないようになっています。 + @@ -400,92 +374,130 @@ section of Chapter 15. ### Enumを使って複数の型を保持する -この章の冒頭で、ベクタは同じ型の値しか保持できないと述べました。 -これは不便なこともあります。 +ベクタは同じ型の値しか保持できません。これは不便なこともあります。 異なる型の要素を保持する必要のあるユースケースは必ず存在します。 -幸運なことに、enumの列挙子は同じenumの型の中に定義されるので、ベクタに異なる型の要素を保持する必要が出たら、enumを定義して使用すればよいのです! +幸運なことに、enumの列挙子は同じenumの型の中に定義されるので、異なる型の要素を表現する単一の型が必要になったら、enumを定義して使用すればよいのです! 例えば、スプレッドシートのある行から値を得ることを考えます。 ここで、その行の中の列には、整数を含むもの、浮動小数点数を含むもの、文字列を含むものがあるとします。 列挙子ごとに異なる値の型を保持するenumが定義できます。 そして、このenumの列挙子は全て同じ型、つまりenumの型、と考えられるわけです。 -ですから、そのenumを保持するベクタを作成でき、結果的に異なる型を保持できるようになるわけです。 -リスト8-10でこれを実演しています。 +ですから、そのenumを保持するためのベクタを作成でき、結果的に異なる型を保持できるようになるわけです。 +リスト8-9でこれを実演しています。 ```rust -{{#rustdoc_include ../listings/ch08-common-collections/listing-08-10/src/main.rs:here}} +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-09/src/main.rs:here}} ``` -リスト8-10:`enum`を定義して、一つのベクタに異なる型の値を保持する +リスト8-9:`enum`を定義して、一つのベクタに異なる型の値を保持する 個々の要素を格納するのにヒープ上で必要となるメモリの量を正確に把握するめに、Rustコンパイラはコンパイル時にベクタに入る型を知る必要があります。 -また、このベクタではどんな型が許容されるのか明示できるという副次的な利点があります。 +また、このベクタではどんな型が許容されるのか明示しなくてはなりません。 もしRustが、ベクタにどんな型でも保持できることを許していたら、ベクタの要素に対して行われる処理に対して、いくつかの型がエラーを引き起こすかもしれません。 enumに加えて`match`式を使うことで、第6章で説明したとおり、あらゆるケースが処理できることを、Rustがコンパイル時に保証することになります。 -プログラムを書いている時点で、プログラムが実行時に取得し、ベクタに格納し得る全ての型を網羅できない場合には、このenumを使ったテクニックはうまくいかないでしょう。 +プログラムが実行時に取得し、ベクタに格納し得る全ての型を網羅できない場合には、このenumを使ったテクニックはうまくいかないでしょう。 代わりにトレイトオブジェクトを使用できます。 こちらは第17章で取り上げます。 これまでにベクタの代表的な使い方をいくつか紹介しました。 標準ライブラリで`Vec`に定義されている多くの有益なメソッドについて、[APIドキュメント][vec-api]を必ず確認するようにしてください。 例えば、`push`に加えて、`pop`というメソッドがあり、これは最後の要素を削除して返します。 + + + +### ベクタをドロップすれば、要素もドロップする + + + +他のあらゆる`struct`(構造体)と同様に、ベクタもスコープを抜ければ解放されます。 +その様子をリスト8-10に示します。 + +```rust +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-10/src/main.rs:here}} +``` + + + +リスト8-10:ベクタとその要素がドロップされる箇所を示す + + + +ベクタがドロップされると、その中身もドロップされます。 +つまり、保持されていた整数値が片付けられるということです。 +借用チェッカーは、ベクタの内容へのいかなる参照も、ベクタ自体が有効な間のみ使用されることを保証します。 + + + それでは次のコレクション型である`String`に移りましょう! [data-types]: ch03-02-data-types.html#データ型 -[nomicon]: ../nomicon/vec.html +[nomicon]: ../nomicon/vec/vec.html [vec-api]: ../std/vec/struct.Vec.html [deref]: ch15-02-deref.html#参照外し演算子で値までポインタを追いかける diff --git a/src/ch08-02-strings.md b/src/ch08-02-strings.md index c04e598c2..dad5d6164 100644 --- a/src/ch08-02-strings.md +++ b/src/ch08-02-strings.md @@ -7,20 +7,20 @@ 第4章で文字列について語りましたが、今度はより掘り下げていきましょう。新参者のRustaceanは、 -3つの概念の組み合わせにより、文字列でよく行き詰まります: Rustのありうるエラーを晒す性質、 +3つの理由の組み合わせにより、文字列でよく行き詰まります: Rustのありうるエラーを晒す性質、 多くのプログラマが思っている以上に文字列が複雑なデータ構造であること、そしてUTF-8です。 これらの要因が、他のプログラミング言語から移ってきた場合、一見困難に見えるように絡み合うわけです。 -コレクションの文脈で文字列を議論することは、有用なことです。なぜなら、文字列はテキストとして解釈された時に有用になる機能を提供するメソッドと、 -バイトのコレクションで実装されているからです。この節では、生成、更新、読み込みのような全コレクションが持つ`String`の処理について語ります。 +文字列は、バイトのコレクションに、そのバイトをテキストとして解釈するときに便利な機能を提供するメソッドを足したものとして実装されているため、コレクションの文脈で文字列を議論していきます。 +この節では、生成、更新、読み込みのような全コレクションが持つ`String`の処理について語ります。 また、`String`が他のコレクションと異なる点についても議論します。具体的には、人間とコンピュータが`String`データを解釈する方法の差異により、 `String`に添え字アクセスする方法がどう複雑なのかということです。 @@ -45,48 +45,30 @@ We’ll first define what we mean by the term *string*. Rust has only one string type in the core language, which is the string slice `str` that is usually seen in its borrowed form `&str`. In Chapter 4, we talked about *string slices*, which are references to some UTF-8 encoded string data stored elsewhere. String -literals, for example, are stored in the binary output of the program and are -therefore string slices. +literals, for example, are stored in the program’s binary and are therefore +string slices. --> まずは、*文字列*という用語の意味を定義しましょう。Rustには、言語の核として1種類しか文字列型が存在しません。 文字列スライスの`str`で、通常借用された形態`&str`で見かけます。第4章で、*文字列スライス*について語りました。 これは、別の場所に格納されたUTF-8エンコードされた文字列データへの参照です。例えば、文字列リテラルは、 -プログラムのバイナリ出力に格納されるので、文字列スライスになります。 +プログラムのバイナリに格納されるので、文字列スライスになります。 -`String`型は、言語の核として組み込まれるのではなく、Rustの標準ライブラリで提供されますが、伸長可能、 -可変、所有権のあるUTF-8エンコードされた文字列型です。RustaceanがRustにおいて「文字列」を指したら、 -どちらかではなく、`String`と文字列スライスの`&str`のことを通常意味します。この節は、大方、 +`String`型は、言語の核として組み込まれるのではなく、Rustの標準ライブラリによって提供されますが、伸長可能、 +可変、所有権のあるUTF-8エンコードされた文字列型です。RustaceanがRustにおいて「文字列」と言うとき、`String`型または文字列スライスの`&str`型のいずれかを指しているかもしれません。この節は、大方、 `String`についてですが、どちらの型もRustの標準ライブラリで重宝されており、 どちらもUTF-8エンコードされています。 - - -また、Rustの標準ライブラリには、他の文字列型も含まれています。`OsString`、`OsStr`、`CString`、`CStr`などです。 -ライブラリクレートにより、文字列データを格納する選択肢はさらに増えます。 -それらの名前が全て`String`か`Str`で終わっているのがわかりますか?所有権ありと借用されたバージョンを指しているのです。 -ちょうど以前見かけた`String`と`&str`のようですね。例えば、これらの文字列型は、異なるエンコード方法でテキストを格納していたり、 -メモリ上の表現が異なったりします。この章では、これらの他の種類の文字列については議論しません; -使用方法やどれが最適かについては、APIドキュメントを参照してください。 - @@ -95,15 +77,18 @@ API documentation for more about how to use them and when each is appropriate. -`Vec`で使用可能な処理の多くが`String`でも使用できます。文字列を生成する`new`関数から始めましょうか。 +`String`は実際のところ、いくつか追加の保障と制限と機能を持つバイトのベクタのラッパーとして実装されているので、`Vec`で使用可能な操作の多くが`String`でも使用できます。 +`Vec`と`String`で同様に機能する関数の例としては、それぞれのインスタンスを作成する`new`関数があります。 リスト8-11に示したようにですね。 ```rust -let mut s = String::new(); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-11/src/main.rs:here}} ``` 文字列は、非常に多くのものに使用されるので、多くの異なる一般的なAPIを使用でき、たくさんの選択肢があるわけです。 冗長に思われるものもありますが、適材適所です!今回の場合、`String::from`と`to_string`は全く同じことをします。 -従って、どちらを選ぶかは、スタイル次第です。 +従って、どちらを選ぶかは、スタイルと可読性次第です。 @@ -243,8 +214,7 @@ as shown in Listing 8-15. リスト8-15の通りです。 ```rust -let mut s = String::from("foo"); -s.push_str("bar"); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-15/src/main.rs:here}} ``` この2行の後、`s`は`foobar`を含むことになります。`push_str`メソッドは、必ずしも引数の所有権を得なくていいので、 -文字列スライスを取ります。例えば、リスト8-16のコードは、中身を`s1`に追加した後、 -`s2`を使えなかったら残念だということを示しています。 +文字列スライスを取ります。例えば、リスト8-16のコードで、中身を`s1`に追加した後も`s2`を使いたいとします。 ```rust -let mut s1 = String::from("foo"); -let s2 = "bar"; -s1.push_str(s2); -println!("s2 is {}", s2); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-16/src/main.rs:here}} ``` `push`メソッドは、1文字を引数として取り、`String`に追加します。リスト8-15は、 -`push`メソッドで*l*を`String`に追加するコードを呈示しています。 +`push`メソッドで“l”を`String`に追加しています。 ```rust -let mut s = String::from("lo"); -s.push('l'); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-17/src/main.rs:here}} ``` -このコードの結果、`s`は`lol`を含むことになるでしょう。 +この結果、`s`は`lol`を含むことになるでしょう。 > 編者注: `lol`は`laughing out loud`(大笑いする)の頭文字からできたスラングです。 > 日本語の`www`みたいなものですね。 @@ -324,25 +289,15 @@ As a result of this code, `s` will contain `lol`. #### `+`演算子、または`format!`マクロで連結 -2つのすでにある文字列を組み合わせたくなることがよくあります。リスト8-18に示したように、 -一つ目の方法は、`+`演算子を使用することです。 +2つのすでにある文字列を組み合わせたくなることがよくあります。 +これを行うための方法の一つは、リスト8-18に示したように、`+`演算子を使用することです。 - - -```rust -let s1 = String::from("Hello, "); -let s2 = String::from("world!"); -let s3 = s1 + &s2; // s1はムーブされ、もう使用できないことに注意 +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-18/src/main.rs:here}} ``` -このコードの結果、`s3`という文字列は、`Hello, world!`を含むことになるでしょう。 +`s3`という文字列は、`Hello, world!`を含むことになるでしょう。 追記の後、`s1`がもう有効でなくなった理由と、`s2`への参照を使用した理由は、 `+`演算子を使用した時に呼ばれるメソッドのシグニチャと関係があります。`+`演算子は、`add`メソッドを使用し、 そのシグニチャは以下のような感じです: @@ -370,28 +325,28 @@ fn add(self, s: &str) -> String { ``` -これは、標準ライブラリにあるシグニチャそのものではありません: 標準ライブラリでは、`add`はジェネリクスで定義されています。 -ここでは、ジェネリックな型を具体的な型に置き換えた`add`のシグニチャを見ており、これは、 -このメソッドを`String`値とともに呼び出した時に起こることです。ジェネリクスについては、第10章で議論します。 +標準ライブラリでは、`add`はジェネリクスと関連型を使用して定義されているのがわかるでしょう。 +ここでは具体的な型で置き換えていますが、これはこのメソッドを`String`値とともに呼び出した時に起こることです。 +ジェネリクスについては、第10章で議論します。 このシグニチャが、`+`演算子の巧妙な部分を理解するのに必要な手がかりになるのです。 -まず、`s2`には`&`がついてます。つまり、`add`関数の`s`引数のために最初の文字列に2番目の文字列の参照を追加するということです: +まず、`s2`には`&`がついてます。つまり、最初の文字列に2番目の文字列の参照を追加するということです。 +これは`add`関数の`s`引数のためのものです: `String`には`&str`を追加することしかできません。要するに2つの`String`値を追加することはできないのです。 でも待ってください。`add`の第2引数で指定されているように、`&s2`の型は、`&str`ではなく、 `&String`ではないですか。では、なぜ、リスト8-18は、コンパイルできるのでしょうか? @@ -413,12 +368,12 @@ after this operation. 2番目に、シグニチャから`add`は`self`の所有権をもらうことがわかります。`self`には`&`がついてい*ない*からです。 @@ -428,47 +383,39 @@ than copying. たくさんのコピーをしているように見えますが、違います; 実装は、コピーよりも効率的です。 複数の文字列を連結する必要が出ると、`+`演算子の振る舞いは扱いにくくなります: ```rust -let s1 = String::from("tic"); -let s2 = String::from("tac"); -let s3 = String::from("toe"); - -let s = s1 + "-" + &s2 + "-" + &s3; +{{#rustdoc_include ../listings/ch08-common-collections/no-listing-01-concat-multiple-strings/src/main.rs:here}} ``` ここで、`s`は`tic-tac-toe`になるでしょう。`+`と`"`文字のせいで何が起きているのかわかりにくいです。 -もっと複雑な文字列の連結には、`format!`マクロを使用することができます: +もっと複雑な文字列の連結には、代わりに`format!`マクロを使用することができます: ```rust -let s1 = String::from("tic"); -let s2 = String::from("tac"); -let s3 = String::from("toe"); - -let s = format!("{}-{}-{}", s1, s2, s3); +{{#rustdoc_include ../listings/ch08-common-collections/no-listing-02-format/src/main.rs:here}} ``` -このコードでも、`s`は`tic-tac-toe`になります。`format!`マクロは、`println!`と同様の動作をしますが、 -出力をスクリーンに行う代わりに、中身を`String`で返すのです。`format!`を使用したコードの方がはるかに読みやすく、 -引数の所有権を奪いません。 +このコードでも、`s`は`tic-tac-toe`になります。`format!`マクロは、`println!`と似た動作をしますが、 +出力をスクリーンに行う代わりに、中身を`String`で返すのです。`format!`を使用したコードの方がはるかに読みやすく、`format!` マクロによって生成されたコードはは参照を使用するので、この呼び出しは引数の所有権を奪いません。 この場合、`len`は4になり、これは、文字列"Hola"を保持するベクタの長さが4バイトであることを意味します。 -これらの各文字は、UTF-8でエンコードすると、1バイトになるのです。しかし、以下の行ではどうでしょうか? -(この文字列は大文字のキリル文字Zeで始まり、アラビア数字の3では始まっていないことに注意してください) +これらの各文字は、UTF-8でエンコードすると、1バイトになるのです。しかし、次の行にはびっくりするかもしれません。 +(この文字列は大文字のキリル文字ゼーで始まり、数字の3では始まっていないことに注意してください) ```rust -let len = String::from("Здравствуйте").len(); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-14/src/main.rs:russian}} ``` -文字列の長さはと問われたら、あなたは12と答えるかもしれません。ところが、Rustの答えは、24です: -“Здравствуйте”をUTF-8でエンコードすると、この長さになります。各Unicodeスカラー値は、2バイトの領域を取るからです。 +文字列の長さはと問われたら、あなたは12と答えるかもしれません。実際には、Rustの答えは、24です: +“Здравствуйте”をUTF-8でエンコードすると、この長さになります。この文字列に含まれる各Unicodeスカラー値は、2バイトの領域を取るからです。 それ故に、文字列のバイトの添え字は、必ずしも有効なUnicodeのスカラー値とは相互に関係しないのです。 デモ用に、こんな非合法なRustコードを考えてください: -```rust,ignore +```rust,ignore,does_not_compile let hello = "Здравствуйте"; let answer = &hello[0]; ``` -`answer`の値は何になるべきでしょうか?最初の文字の`З`になるべきでしょうか?UTF-8エンコードされた時、 -`З`の最初のバイトは`208`、2番目は`151`になるので、`answer`は実際、`208`になるべきですが、 +`answer`の値は、最初の文字の`З`にはならないことを知っているでしょう。UTF-8エンコードされた時、 +`З`の最初のバイトは`208`、2番目は`151`になるので、`answer`は実際には`208`になりそうですが、 `208`は単独では有効な文字ではありません。この文字列の最初の文字を求めている場合、`208`を返すことは、 ユーザの望んでいるものではないでしょう; しかしながら、Rustには、バイト添え字0の位置には、そのデータしかないのです。 文字列がラテン文字のみを含む場合でも、ユーザは一般的にバイト値が返ることを望みません: `&"hello"[0]`がバイト値を返す有効なコードだったら、`h`ではなく、`104`を返すでしょう。 -予期しない値を返し、すぐには判明しないバグを引き起こさないために、Rustはこのコードを全くコンパイルせず、 + + +答えは、予期しない値を返し、すぐには判明しないバグを引き起こさないために、Rustはこのコードを全くコンパイルせず、 開発過程の早い段階で誤解を防いでくれるのです。 文字列に添え字アクセスするのは、しばしば悪い考えです。文字列添え字処理の戻り値の型が明瞭ではないからです: バイト値、文字、書記素クラスタ、あるいは文字列スライスにもなります。故に、文字列スライスを生成するのに、 -添え字を使う必要が本当に出た場合にコンパイラは、もっと特定するよう求めてきます。添え字アクセスを特定し、 -文字列スライスが欲しいと示唆するためには、`[]`で1つの数値により添え字アクセスするのではなく、 +添え字を使う必要が本当に出た場合にコンパイラは、もっと特定するよう求めてきます。 + + + +`[]`で1つの数値により添え字アクセスするのではなく、 範囲とともに`[]`を使って、特定のバイトを含む文字列スライスを作ることができます: ```rust @@ -714,16 +659,16 @@ Earlier, we mentioned that each of these characters was 2 bytes, which means `s`は`Зд`になります。 -`&hello[0..1]`と使用したら、何が起きるでしょうか?答え: Rustはベクタの非合法な添え字にアクセスしたかのように、 -実行時にパニックするでしょう: +`&hello[0..1]`のようにして、文字を構成するバイトの一部のみをスライスしようとすると、 +Rustはベクタの非合法な添え字にアクセスしたかのように実行時にパニックするでしょう: -```text -thread 'main' panicked at 'byte index 1 is not a char boundary; it is inside 'З' (bytes 0..2) of `Здравствуйте`', src/libcore/str/mod.rs:2188:4 -('main'スレッドは「バイト添え字1は文字の境界ではありません; `Здравствуйте`の'З'(バイト番号0から2)の中です」でパニックしました) +```console +{{#include ../listings/ch08-common-collections/output-only-01-not-char-boundary/output.txt}} ``` -もし、個々のUnicodeスカラー値に対して処理を行う必要があったら、最適な方法は`chars`メソッドを使用するものです。 -“नमस्ते”に対して`chars`を呼び出したら、分解して6つの`char`型の値を返すので、各要素にアクセスするには、 +文字列の部分に対して操作を行うための最良の方法は、文字に対して操作したいのかバイトに対して操作したいのかを明示することです。 +個々のUnicodeスカラー値に対しては、`chars`メソッドを使用してください。 +“Зд”に対して`chars`を呼び出したら、分解して2つの`char`型の値を返すので、各要素にアクセスするには、 その結果を走査すればいいわけです: ```rust -for c in "नमस्ते".chars() { - println!("{}", c); +for c in "Зд".chars() { + println!("{c}"); } ``` @@ -769,39 +715,34 @@ This code will print the following: このコードは、以下のように出力します: ```text -न -म -स -् -त -े +З +д ``` -`bytes`メソッドは、各バイトをそのまま返すので、最適になることもあるかもしれません: +あるいは、`bytes`メソッドは各バイトをそのまま返すので、ドメインによってはこちらが適切かもしれません: ```rust -for b in "नमस्ते".bytes() { - println!("{}", b); +for b in "Зд".bytes() { + println!("{b}"); } ``` -このコードは、`String`をなす18バイトを出力します: +このコードは、この文字列をなす4バイトを出力します: ```text -224 -164 -// --snip-- -165 -135 +208 +151 +208 +180 ``` -書記素クラスタを文字列から得る方法は複雑なので、この機能は標準ライブラリでは提供されていません。 +デーヴァナーガリー文字を含むような文字列から書記素クラスタを得る方法は複雑なので、この機能は標準ライブラリでは提供されていません。 この機能が必要なら、[crates.io](https://crates.io)でクレートを入手可能です。 + +一方で良い面としては、こうした複雑な状況に正しく対処するために、標準ライブラリが`String`と`&str`型の上に構築された多数の機能を提供していることです。 +文字列内の検索のための`contains`や、文字列の一部を別の文字列で置換するための`replace`などの便利なメソッドについて、ドキュメントを確認してみてください。 + diff --git a/src/ch08-03-hash-maps.md b/src/ch08-03-hash-maps.md index f468130b9..23d8bbc41 100644 --- a/src/ch08-03-hash-maps.md +++ b/src/ch08-03-hash-maps.md @@ -1,25 +1,25 @@ ## キーとそれに紐づいた値をハッシュマップに格納する 一般的なコレクションのトリを飾るのは、*ハッシュマップ*です。型`HashMap`は、 -`K`型のキーと`V`型の値の対応関係を保持します。これを*ハッシュ関数*を介して行います。 +`K`型のキーと`V`型の値の対応関係を*ハッシュ関数*を使用して保持します。 ハッシュ関数は、キーと値のメモリ配置方法を決めるものです。多くのプログラミング言語でもこの種のデータ構造はサポートされていますが、 -しばしば名前が違います。hash、map、object、ハッシュテーブル、連想配列など、枚挙に(いとま)はありません。 +しばしば名前が違います。hash、map、object、ハッシュテーブル、辞書、連想配列など、枚挙に(いとま)はありません。 -空のハッシュマップを`new`で作り、要素を`insert`で追加することができます。リスト8-20では、 -名前がブルーとイエローの2チームのスコアを追いかけています。ブルーチームは10点から、イエローチームは50点から始まります。 +空のハッシュマップを作成する方法のひとつは`new`を使用する方法で、その後要素を`insert`で追加することができます。 +リスト8-20では、名前が*ブルー*と*イエロー*の2チームのスコアを追いかけています。 +ブルーチームは10点から、イエローチームは50点から始まります。 ```rust -use std::collections::HashMap; - -let mut scores = HashMap::new(); - -scores.insert(String::from("Blue"), 10); -scores.insert(String::from("Yellow"), 50); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-20/src/main.rs:here}} ``` 最初に標準ライブラリのコレクション部分から`HashMap`を`use`する必要があることに注意してください。 @@ -87,57 +83,74 @@ standard library; there's no built-in macro to construct them, for example. ベクタと全く同様に、ハッシュマップはデータをヒープに保持します。この`HashMap`はキーが`String`型、 -値は`i32`型です。ベクタのように、ハッシュマップは均質です: キーは全て同じ型でなければならず、 +値は`i32`型です。ベクタのように、ハッシュマップは均質です: すべてのキーは互いに同じ型でなければならず、 値も全て同じ型でなければなりません。 -ハッシュマップを生成する別の方法は、タプルのベクタに対して`collect`メソッドを使用するものです。 -ここで、各タプルは、キーと値から構成されています。`collect`メソッドはいろんなコレクション型にデータをまとめ上げ、 -そこには`HashMap`も含まれています。例として、チーム名と初期スコアが別々のベクタに含まれていたら、 -`zip`メソッドを使ってタプルのベクタを作り上げることができ、そこでは「ブルー」は10とペアになるなどします。 -リスト8-21に示したように、それから`collect`メソッドを使って、そのタプルのベクタをハッシュマップに変換することができるわけです。 +### ハッシュマップの値にアクセスする -```rust -use std::collections::HashMap; + -let teams = vec![String::from("Blue"), String::from("Yellow")]; -let initial_scores = vec![10, 50]; +リスト8-21に示したように、キーを`get`メソッドに提供することで、ハッシュマップから値を取り出すことができます。 -let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect(); +```rust +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-21/src/main.rs:here}} ``` + +リスト8-21: ハッシュマップに保持されたブルーチームのスコアにアクセスする + + + +ここで、`score`はブルーチームに紐づけられた値になり、結果は`10`となるでしょう。 +`get`メソッドは`Option<&V>`を返します; +キーに対応する値がハッシュマップになかったら、`get`は`None`を返すでしょう。 +このプログラムはこの`Option`に対して、`Option<&i32>`ではなく`Option`を得るために`copied`を呼び出し、 +その後、`scores`がそのキーに対応するエントリを持たない場合は`score`を0に設定するために、`unwrap_or`を呼び出して対処します。 + + -リスト8-21: チームのリストとスコアのリストからハッシュマップを作る +ベクタのように、`for`ループでハッシュマップのキーと値のペアを走査することができます: + +```rust +{{#rustdoc_include ../listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs:here}} +``` -ここでは、`HashMap<_, _>`という型注釈が必要になります。なぜなら、いろんなデータ構造に`まとめ上げる`ことができ、 -コンパイラは指定しない限り、どれを所望なのかわからないからです。ところが、キーと値の型引数については、 -アンダースコアを使用しており、コンパイラはベクタのデータ型に基づいてハッシュマップが含む型を推論することができるのです。 +このコードは、各ペアを任意の順番で出力します: + +```text +Yellow: 50 +Blue: 10 +``` 値への参照をハッシュマップに挿入したら、値はハッシュマップにムーブされません。参照が指している値は、 最低でもハッシュマップが有効な間は、有効でなければなりません。これらの問題について詳細には、 -第10章の「ライフタイムで参照を有効化する」節で語ります。 - - - -### ハッシュマップの値にアクセスする - - - -リスト8-23に示したように、キーを`get`メソッドに提供することで、ハッシュマップから値を取り出すことができます。 - -```rust -use std::collections::HashMap; - -let mut scores = HashMap::new(); - -scores.insert(String::from("Blue"), 10); -scores.insert(String::from("Yellow"), 50); - -let team_name = String::from("Blue"); -let score = scores.get(&team_name); -``` - - - -リスト8-23: ハッシュマップに保持されたブルーチームのスコアにアクセスする +第10章の[「ライフタイムで参照を有効化する」][validating-references-with-lifetimes]節で語ります。 - -ここで、`score`はブルーチームに紐づけられた値になり、結果は`Some(&10)`となるでしょう。 -結果は`Some`に包まれます。というのも、`get`は`Option<&V>`を返すからです; キーに対応する値がハッシュマップになかったら、 -`get`は`None`を返すでしょう。プログラムは、この`Option`を第6章で講義した方法のどれかで扱う必要があるでしょう。 - - -ベクタのように、`for`ループでハッシュマップのキーと値のペアを走査することができます: - -```rust -use std::collections::HashMap; - -let mut scores = HashMap::new(); - -scores.insert(String::from("Blue"), 10); -scores.insert(String::from("Yellow"), 50); - -for (key, value) in &scores { - println!("{}: {}", key, value); -} -``` +### ハッシュマップを更新する -このコードは、各ペアを任意の順番で出力します: - -```text -Yellow: 50 -Blue: 10 -``` +キーと値のペアの数は伸長可能ですが、それぞれの一意なキーには同時に1つの値しか紐づけることができません(ただし逆は可能です: +例えば、`scores`ハッシュマップ内にブルーチームとイエローチームはともに値10を保存することができます)。 -### ハッシュマップを更新する - - - -キーと値の数は伸長可能なものの、各キーには1回に1つの値しか紐づけることができません。 ハッシュマップ内のデータを変えたい時は、すでにキーに値が紐づいている場合の扱い方を決めなければなりません。 古い値を新しい値で置き換えて、古い値を完全に無視することもできます。古い値を保持して、 新しい値を無視し、キーにまだ値が*ない*場合に新しい値を追加するだけにすることもできます。 @@ -302,32 +239,25 @@ of these! キーと値をハッシュマップに挿入し、同じキーを異なる値で挿入したら、そのキーに紐づけられている値は置換されます。 -リスト8-24のコードは、`insert`を二度呼んでいるものの、ハッシュマップには一つのキーと値の組しか含まれません。 +リスト8-23のコードは、`insert`を二度呼んでいるものの、ハッシュマップには一つのキーと値の組しか含まれません。 なぜなら、ブルーチームキーに対する値を2回とも挿入しているからです。 ```rust -use std::collections::HashMap; - -let mut scores = HashMap::new(); - -scores.insert(String::from("Blue"), 10); -scores.insert(String::from("Blue"), 25); - -println!("{:?}", scores); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-23/src/main.rs:here}} ``` -リスト8-24: 特定のキーで保持された値を置き換える +リスト8-23: 特定のキーで保持された値を置き換える + + -#### キーに値がなかった時のみ値を挿入する +#### キーが存在しない場合のみキーと値を追加する + +特定のキーがハッシュマップ内に値とともに存在しているか確認して、以下のアクションを取ることは一般的でしょう: +キーがハッシュマップに存在する場合は、既存の値はそのままにします。 +キーが存在しない場合は、そのキーとそれに対応する値を挿入します。 + + -特定のキーに値があるか確認することは一般的であり、存在しない時に値を挿入することも一般的です。 ハッシュマップには、これを行う`entry`と呼ばれる特別なAPIがあり、これは、引数としてチェックしたいキーを取ります。 この`entry`メソッドの戻り値は、`Entry`と呼ばれるenumであり、これは存在したりしなかったりする可能性のある値を表します。 イエローチームに対するキーに値が紐づけられているか否か確認したくなったとしましょう。存在しなかったら、 -50という値を挿入したく、ブルーチームに対しても同様です。`entry`APIを使用すれば、コードはリスト8-25のようになります。 +50という値を挿入したく、ブルーチームに対しても同様です。`entry`APIを使用すれば、コードはリスト8-24のようになります。 ```rust -use std::collections::HashMap; - -let mut scores = HashMap::new(); -scores.insert(String::from("Blue"), 10); - -scores.entry(String::from("Yellow")).or_insert(50); -scores.entry(String::from("Blue")).or_insert(50); - -println!("{:?}", scores); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-24/src/main.rs:here}} ``` -リスト8-25: `entry`メソッドを使ってキーに値がない場合だけ挿入する +リスト8-24: `entry`メソッドを使ってキーに値がない場合だけ挿入する `Entry`上の`or_insert`メソッドは、対応する`Entry`キーが存在した時にそのキーに対する値への可変参照を返すために定義されており、 @@ -391,14 +326,14 @@ logic ourselves, and in addition, plays more nicely with the borrow checker. そのロジックを自分で書くよりもはるかに綺麗な上に、borrow checkerとも親和性が高くなります。 -リスト8-25のコードを実行すると、`{"Yellow": 50, "Blue": 10}`と出力するでしょう。 +リスト8-24のコードを実行すると、`{"Yellow": 50, "Blue": 10}`と出力するでしょう。 最初の`entry`呼び出しは、まだイエローチームに対する値がないので、値50でイエローチームのキーを挿入します。 `entry`の2回目の呼び出しはハッシュマップを変更しません。なぜなら、ブルーチームには既に10という値があるからです。 @@ -410,83 +345,88 @@ value 10. ハッシュマップの別の一般的なユースケースは、キーの値を探し、古い値に基づいてそれを更新することです。 -例えば、リスト8-26は、各単語があるテキストに何回出現するかを数え上げるコードを示しています。 +例えば、リスト8-25は、各単語があるテキストに何回出現するかを数え上げるコードを示しています。 キーに単語を入れたハッシュマップを使用し、その単語を何回見かけたか追いかけるために値を増やします。 -ある単語を見かけたのが最初だったら、まず0という値を挿入します: +ある単語を見かけたのが最初だったら、まず0という値を挿入します。 ```rust -use std::collections::HashMap; - -let text = "hello world wonderful world"; - -let mut map = HashMap::new(); - -for word in text.split_whitespace() { - let count = map.entry(word).or_insert(0); - *count += 1; -} - -println!("{:?}", map); +{{#rustdoc_include ../listings/ch08-common-collections/listing-08-25/src/main.rs:here}} ``` -リスト8-26: 単語とカウントを保持するハッシュマップを使って単語の出現数をカウントする +リスト8-25: 単語とカウントを保持するハッシュマップを使って単語の出現数をカウントする section that +iterating over a hash map happens in an arbitrary order. --> このコードは、`{"world": 2, "hello": 1, "wonderful": 1}`と出力するでしょう。 -`or_insert`関数は実際、このキーに対する値への可変参照(`&mut V`)を返すのです。 +同じキー/値ペアが、異なる順で印字されるかもしれません: +[「ハッシュマップの値にアクセスする」][access]の節で説明した、 +ハッシュマップの走査は任意の順で起こるということを思い出してください。 + + + +`split_whitespace`メソッドは、`text`の値から、ホワイトスペースによって区切られた部分スライスを走査するイテレータを返します。 +`or_insert`関数は、指定されたキーに対する値への可変参照(`&mut V`)を返すのです。 ここでその可変参照を`count`変数に保持しているので、その値に代入するには、 まずアスタリスク(`*`)で`count`を参照外ししなければならないのです。この可変参照は、 `for`ループの終端でスコープを抜けるので、これらの変更は全て安全であり、借用規則により許可されるのです。 ### ハッシュ関数 -標準では、`HashMap`はサービス拒否(DoS)アタックに対して抵抗を示す暗号学的に安全なハッシュ関数を使用します。 +`HashMap`はデフォルトでは、ハッシュテーブルに関するサービス拒否(DoS)攻撃に対する耐性を提供する、*SipHash*と呼ばれるハッシュ関数を使用します[^siphash]。 これは、利用可能な最速のハッシュアルゴリズムではありませんが、パフォーマンスの欠落と引き換えに安全性を得るというトレードオフは、 価値があります。自分のコードをプロファイリングして、自分の目的では標準のハッシュ関数は遅すぎると判明したら、 -異なる*hasher*を指定することで別の関数に切り替えることができます。hasherとは、 +異なるhasherを指定することで別の関数に切り替えることができます。*hasher*とは、 `BuildHasher`トレイトを実装する型のことです。トレイトについてとその実装方法については、第10章で語ります。 -必ずしも独自のhasherを1から作り上げる必要はありません; [crates.io](https://crates.io)には、 +必ずしも独自のhasherを1から作り上げる必要はありません; [crates.io](https://crates.io/)には、 他のRustユーザによって共有された多くの一般的なハッシュアルゴリズムを実装したhasherを提供するライブラリがあります。 +[^siphash]: [https://en.wikipedia.org/wiki/SipHash](https://en.wikipedia.org/wiki/SipHash) + @@ -503,21 +443,21 @@ some exercises you should now be equipped to solve: 多くの機能を提供してくれるでしょう。今なら解決可能なはずの練習問題を用意しました: -* 整数のリストが与えられ、ベクタを使ってmean(平均値)、median(ソートされた時に真ん中に来る値)、 +* 整数のリストが与えられ、ベクタを使ってmedian(ソートされた時に真ん中に来る値)、 mode(最も頻繁に出現する値; ハッシュマップがここでは有効活用できるでしょう)を返してください。 * 文字列をピッグ・ラテン(`訳注`: 英語の言葉遊びの一つ)に変換してください。各単語の最初の子音は、 単語の終端に移り、"ay"が足されます。従って、"first"は"irst-fay"になります。ただし、 @@ -535,9 +475,19 @@ and hash maps have that will be helpful for these exercises! 標準ライブラリのAPIドキュメントには、この練習問題に有用な、ベクタ、文字列、ハッシュマップのメソッドが解説されています。 + +処理が失敗することもあるような、より複雑なプログラムに入り込んできています。 +ということは、エラーの処理法について議論するのにぴったりということです。次はそれをします! + + -処理が失敗することもあるような、より複雑なプログラムに入り込んできています; ということは、 -エラーの処理法について議論するのにぴったりということです。次はそれをします! +[validating-references-with-lifetimes]: +ch10-03-lifetime-syntax.html#ライフタイムで参照を検証する +[access]: #ハッシュマップの値にアクセスする diff --git a/src/ch09-00-error-handling.md b/src/ch09-00-error-handling.md index 8a389f8e0..d3c3865de 100644 --- a/src/ch09-00-error-handling.md +++ b/src/ch09-00-error-handling.md @@ -5,45 +5,45 @@ # エラー処理 -Rustの信頼性への傾倒は、エラー処理にも及びます。ソフトウェアにおいて、エラーは生きている証しです。 -従って、Rustには何かがおかしくなる場面を扱う機能がたくさんあります。多くの場面で、 +ソフトウェアにおいて、エラーは避けられない現実です。 +そのため、Rustには何かがおかしくなる場面に対処するための機能がたくさんあります。多くの場面で、 コンパイラは、プログラマにエラーの可能性を知り、コードのコンパイルが通るまでに何かしら対応を行うことを要求してきます。 この要求により、エラーを発見し、コードを実用に供する前に適切に対処していることを確認することでプログラムを頑健なものにしてくれるのです! Rustでは、エラーは大きく二つに分類されます: *回復可能*と*回復不能*なエラーです。 -ファイルが見つからないなどの回復可能なエラーには、問題をユーザに報告し、処理を再試行することが合理的になります。 -回復不能なエラーは、常にバグの兆候です。例えば、配列の境界を超えた箇所にアクセスしようとすることなどです。 +*ファイルが見つからない*などの回復可能なエラーには、ほとんどの場合は単に問題をユーザに報告し、処理を再試行したいことでしょう。 +回復不能なエラー、例えば配列の境界を超えた箇所にアクセスしようとすることなどは、常にバグの兆候であり、直ちにプログラムを停止したいことでしょう。 多くの言語では、この2種のエラーを区別することはなく、例外などの機構を使用して同様に扱います。 -Rustには例外が存在しません。代わりに、回復可能なエラーには`Result`値があり、 +Rustには例外が存在しません。代わりに、回復可能なエラーには`Result`型があり、 プログラムが回復不能なエラーに遭遇した時には、実行を中止する`panic!`マクロがあります。 この章では、まず`panic!`の呼び出しを講義し、それから`Result`を戻り値にする話をします。 加えて、エラーからの回復を試みるか、実行を中止するか決定する際に考慮すべき事項についても、探究しましょう。 diff --git a/src/ch09-01-unrecoverable-errors-with-panic.md b/src/ch09-01-unrecoverable-errors-with-panic.md index a8c8bded9..70c0c5a2b 100644 --- a/src/ch09-01-unrecoverable-errors-with-panic.md +++ b/src/ch09-01-unrecoverable-errors-with-panic.md @@ -6,25 +6,35 @@ -時として、コードで悪いことが起きるものです。そして、それに対してできることは何もありません。 -このような場面で、Rustには`panic!`マクロが用意されています。`panic!`マクロが実行されると、 -プログラムは失敗のメッセージを表示し、スタックを巻き戻し掃除して、終了します。これが最もありふれて起こるのは、 -何らかのバグが検出された時であり、プログラマには、どうエラーを処理すればいいか明確ではありません。 +時として、コード内で悪いことが起き、それに対してできることは何も無い、ということがあるでしょう。 +このような場面で、Rustには`panic!`マクロが用意されています。 +実際にパニックを発生させる方法は2つあります: +コードをパニックさせるような操作(配列にその終端を超えてアクセスするなど)を行う方法と、明示的に`panic!`マクロを呼び出す方法です。 +いずれの場合でも、プログラムでパニックが発生します。 +デフォルトでは、これらのパニックは失敗メッセージを出力し、スタックを巻き戻し、片付け、プログラムを終了させます。 +パニックが発生したときにはそのパニックの発生源を特定しやすくするために、 +環境変数を介してコールスタックを表示するように指示することもできます。 + -> ### パニックに対してスタックを巻き戻すか異常終了するか +> ### パニックに対してスタックを巻き戻すかアボートするか > -> 標準では、パニックが発生すると、プログラムは*巻き戻し*を始めます。つまり、言語がスタックを遡り、 -> 遭遇した各関数のデータを片付けるということです。しかし、この遡りと片付けはすべきことが多くなります。 -> 対立案は、即座に異常終了し、片付けをせずにプログラムを終了させることです。そうなると、プログラムが使用していたメモリは、 +> デフォルトでは、パニックが発生すると、プログラムは*巻き戻し*を始めます。 +> つまり、コンパイラ生成コードがスタックを遡り、遭遇した各関数のデータを片付けるということです。 +> しかし、この遡行と片付けはすべきことが多くなります。そのためRustでは、 +> 即座に*アボート*し、片付けをせずにプログラムを終了させることを、代替として選択できるようになっています。 +> +> そうなると、プログラムが使用していたメモリは、 > OSが片付ける必要があります。プロジェクトにおいて、実行可能ファイルを極力小さくする必要があれば、 > *Cargo.toml*ファイルの適切な`[profile]`欄に`panic = 'abort'`を追記することで、 -> パニック時に巻き戻しから異常終了するように切り替えることができます。例として、 -> リリースモード時に異常終了するようにしたければ、以下を追記してください: +> パニック時に巻き戻しからアボートするように切り替えることができます。例として、 +> リリースモード時にアボートするようにしたければ、以下を追記してください: > > ```toml > [profile.release] @@ -64,10 +77,8 @@ Let’s try calling `panic!` in a simple program: ファイル名: src/main.rs -```rust,should_panic -fn main() { - panic!("crash and burn"); //クラッシュして炎上 -} +```rust,should_panic,panics +{{#rustdoc_include ../listings/ch09-error-handling/no-listing-01-panic/src/main.rs}} ``` `panic!`の呼び出しが、最後の2行に含まれるエラーメッセージを発生させているのです。 1行目にパニックメッセージとソースコード中でパニックが発生した箇所を示唆しています: -*src/main.rs:2:4*は、*src/main.rs*ファイルの2行目4文字目であることを示しています。 +*src/main.rs:2:5*は、*src/main.rs*ファイルの2行目5文字目であることを示しています。 この場合、示唆される行は、自分のコードの一部で、その箇所を見に行けば、`panic!`マクロ呼び出しがあるわけです。 それ以外では、`panic!`呼び出しが、自分のコードが呼び出しているコードの一部になっている可能性もあるわけです。 エラーメッセージで報告されるファイル名と行番号が、結果的に`panic!`呼び出しに導いた自分のコードの行ではなく、 `panic!`マクロが呼び出されている他人のコードになるでしょう。`panic!`呼び出しの発生元である関数のバックトレースを使用して、 -問題を起こしている自分のコードの箇所を割り出すことができます。バックトレースがどんなものか、次に議論しましょう。 +問題を起こしている自分のコードの箇所を割り出すことができます。次はバックトレースについてはより詳しく議論しましょう。 別の例を眺めて、自分のコードでマクロを直接呼び出す代わりに、コードに存在するバグにより、 ライブラリで`panic!`呼び出しが発生するとどんな感じなのか確かめてみましょう。リスト9-1は、 -添え字でベクタの要素にアクセスを試みる何らかのコードです。 +ベクタに有効な添え字の範囲の外の添え字でアクセスを試みるコードです。 ここでは、ベクタの100番目の要素(添え字は0始まりなので添え字99)にアクセスを試みていますが、ベクタには3つしか要素がありません。 @@ -165,19 +166,19 @@ would be correct. 無効な添え字を渡せば、ここでRustが返せて正しいと思われる要素は何もないわけです。 -他の言語(Cなど)では、この場面で欲しいものではないにもかかわらず、まさしく要求したものを返そうとしてきます: -メモリがベクタに属していないにもかかわらず、ベクタ内のその要素に対応するメモリ上の箇所にあるものを何か返してくるのです。 -これは、*バッファー外読み出し*(buffer overread; `訳注`: バッファー読みすぎとも解釈できるか)と呼ばれ、 -攻撃者が、配列の後に格納された読めるべきでないデータを読み出せるように添え字を操作できたら、 +Cでは、データ構造の終端を超えて読み込みを行おうとすることは未定義動作です。 +メモリがデータ構造に属していないにもかかわらず、そのデータ構造内のその要素に対応するメモリ上の箇所にある何かを返してくるかもしれません。 +これは、*バッファオーバーリード* (*buffer overread*)と呼ばれ、 +攻撃者が、データ構造の後に格納された読めるべきでないデータを読み出せるように添え字を操作できたら、 セキュリティ脆弱性につながる可能性があります。 - -このエラーは、自分のファイルではない*vec.rs*ファイルを指しています。 -標準ライブラリの`Vec`の実装です。ベクタ`v`に対して`[]`を使った時に走るコードは、 -*vec.rs*に存在し、ここで実際に`panic!`が発生しているのです。 - - +このエラーは*main.rs*の4行目を指していて、ここではインデックス99にアクセスを試みています。 その次の注釈行は、`RUST_BACKTRACE`環境変数をセットして、まさしく何が起き、 エラーが発生したのかのバックトレースを得られることを教えてくれています。 *バックトレース*とは、ここに至るまでに呼び出された全関数の一覧です。Rustのバックトレースも、 他の言語同様に動作します: バックトレースを読むコツは、頭からスタートして自分のファイルを見つけるまで読むことです。 -そこが、問題の根源になるのです。自分のファイルを言及している箇所以前は、自分のコードで呼び出したコードになります; -以後は、自分のコードを呼び出しているコードになります。これらの行には、Rustの核となるコード、標準ライブラリのコード、 +そこが、問題が発生した場所です。この場所より上の行は、自分のコードが呼び出したコードになります; +それより下の行は、自分のコードを呼び出しているコードになります。これらの前後の行には、Rustの核となるコード、標準ライブラリのコード、 使用しているクレートなどが含まれるかもしれません。`RUST_BACKTRACE`環境変数を0以外の値にセットして、 バックトレースを出力してみましょう。リスト9-2のような出力が得られるでしょう。 -```text + + +```console $ RUST_BACKTRACE=1 cargo run - Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs - Running `target/debug/panic` -thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', /checkout/src/liballoc/vec.rs:1555:10 +thread 'main' panicked at src/main.rs:4:6: +index out of bounds: the len is 3 but the index is 99 stack backtrace: - 0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace - at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49 - 1: std::sys_common::backtrace::_print - at /checkout/src/libstd/sys_common/backtrace.rs:71 - 2: std::panicking::default_hook::{{closure}} - at /checkout/src/libstd/sys_common/backtrace.rs:60 - at /checkout/src/libstd/panicking.rs:381 - 3: std::panicking::default_hook - at /checkout/src/libstd/panicking.rs:397 - 4: std::panicking::rust_panic_with_hook - at /checkout/src/libstd/panicking.rs:611 - 5: std::panicking::begin_panic - at /checkout/src/libstd/panicking.rs:572 - 6: std::panicking::begin_panic_fmt - at /checkout/src/libstd/panicking.rs:522 - 7: rust_begin_unwind - at /checkout/src/libstd/panicking.rs:498 - 8: core::panicking::panic_fmt - at /checkout/src/libcore/panicking.rs:71 - 9: core::panicking::panic_bounds_check - at /checkout/src/libcore/panicking.rs:58 - 10: as core::ops::index::Index>::index - at /checkout/src/liballoc/vec.rs:1555 - 11: panic::main - at src/main.rs:4 - 12: __rust_maybe_catch_panic - at /checkout/src/libpanic_unwind/lib.rs:99 - 13: std::rt::lang_start - at /checkout/src/libstd/panicking.rs:459 - at /checkout/src/libstd/panic.rs:361 - at /checkout/src/libstd/rt.rs:61 - 14: main - 15: __libc_start_main - 16: + 0: rust_begin_unwind + at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/std/src/panicking.rs:645:5 + 1: core::panicking::panic_fmt + at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/panicking.rs:72:14 + 2: core::panicking::panic_bounds_check + at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/panicking.rs:208:5 + 3: >::index + at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/slice/index.rs:255:10 + 4: core::slice::index:: for [T]>::index + at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/slice/index.rs:18:9 + 5: as core::ops::index::Index>::index + at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/alloc/src/vec/mod.rs:2770:9 + 6: panic::main + at ./src/main.rs:4:6 + 7: core::ops::function::FnOnce::call_once + at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/ops/function.rs:250:5 +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. ``` -リスト9-2の出力で、バックトレースの11行目が問題発生箇所を指し示しています: *src/main.rs*の4行目です。 -プログラムにパニックしてほしくなければ、自分のファイルについて言及している最初の行で示されている箇所が、 -どのようにパニックを引き起こす値でこの箇所にたどり着いたか割り出すために調査を開始すべき箇所になります。 -バックトレースの使用法を模擬するためにわざとパニックするコードを書いたリスト9-1において、 -パニックを解消する方法は、3つしか要素のないベクタの添え字99の要素を要求しないことです。 +リスト9-2の出力で、バックトレースの6行目が問題発生箇所を指し示しています: *src/main.rs*の4行目です。 +プログラムにパニックしてほしくなければ、自分のファイルについて言及している最初の行で示されている箇所から調査を開始すべきです。 +わざとパニックするコードを書いたリスト9-1において、パニックを解消する方法は、 +ベクタの添え字の範囲を超えた要素を要求しないようにすることです。 将来コードがパニックしたら、パニックを引き起こすどんな値でコードがどんな動作をしているのかと、 代わりにコードは何をすべきなのかを算出する必要があるでしょう。 -この章の後ほど、「`panic!`するか`panic!`するまいか」節で`panic!`とエラー状態を扱うのに`panic!`を使うべき時と使わぬべき時に戻ってきます。 +この章の後ほど、[「`panic!`すべきかするまいか」][to-panic-or-not-to-panic]節で`panic!`とエラー状態を扱うのに`panic!`を使うべき時と使わぬべき時に戻ってきます。 次は、`Result`を使用してエラーから回復する方法を見ましょう。 + + + +[to-panic-or-not-to-panic]: +ch09-03-to-panic-or-not-to-panic.html#panicすべきかするまいか diff --git a/src/ch09-02-recoverable-errors-with-result.md b/src/ch09-02-recoverable-errors-with-result.md index 65be5fb61..205b115be 100644 --- a/src/ch09-02-recoverable-errors-with-result.md +++ b/src/ch09-02-recoverable-errors-with-result.md @@ -6,9 +6,9 @@ @@ -17,16 +17,14 @@ file instead of terminating the process. ファイルが存在しないために処理が失敗したら、プロセスを停止するのではなく、ファイルを作成したいことがあります。 -第2章の[「`Result`型で失敗する可能性に対処する」][handle_failure]で`Result` enumが以下のように、 +第2章の[「`Result`で失敗の可能性を扱う」][handle_failure]で`Result` enumが以下のように、 `Ok`と`Err`の2列挙子からなるよう定義されていることを思い出してください: -[handle_failure]: ch02-00-guessing-game-tutorial.html#result型で失敗の可能性を扱う - ```rust enum Result { Ok(T), @@ -40,15 +38,15 @@ detail in Chapter 10. What you need to know right now is that `T` represents the type of the value that will be returned in a success case within the `Ok` variant, and `E` represents the type of the error that will be returned in a failure case within the `Err` variant. Because `Result` has these generic type -parameters, we can use the `Result` type and the functions that the standard -library has defined on it in many different situations where the successful -value and error value we want to return may differ. +parameters, we can use the `Result` type and the functions defined on it in +many different situations where the successful value and error value we want to +return may differ. --> `T`と`E`は、ジェネリックな型引数です: ジェネリクスについて詳しくは、第10章で議論します。 たった今知っておく必要があることは、`T`が成功した時に`Ok`列挙子に含まれて返される値の型を表すことと、 `E`が失敗した時に`Err`列挙子に含まれて返されるエラーの型を表すことです。`Result`はこのようなジェネリックな型引数を含むので、 -標準ライブラリ上に定義されている`Result`型や関数などを、成功した時とエラーの時に返したい値が異なるような様々な場面で使用できるのです。 +`Result`型とその上に定義されている関数を、成功した時とエラーの時に返したい値が異なるような様々な場面で使用できるのです。 - -`File::open`が`Result`を返すとどう知るのでしょうか?標準ライブラリのAPIドキュメントを参照することもできますし、 -コンパイラに尋ねることもできます!`f`に関数の戻り値では*ない*と判明している型注釈を与えて、 -コードのコンパイルを試みれば、コンパイラは型が合わないと教えてくれるでしょう。そして、エラーメッセージは、 -`f`の*実際の*型を教えてくれるでしょう。試してみましょう!`File::open`の戻り値の型は`u32`ではないと判明しているので、 -`let f`文を以下のように変更しましょう: - -```rust,ignore -let f: u32 = File::open("hello.txt"); -``` - - -これでコンパイルしようとすると、以下のような出力が得られます: - -```text -error[E0308]: mismatched types -(エラー: 型が合いません) - --> src/main.rs:4:18 - | -4 | let f: u32 = File::open("hello.txt"); - | ^^^^^^^^^^^^^^^^^^^^^^^ expected u32, found enum -`std::result::Result` - | - = note: expected type `u32` - (注釈: 予期した型は`u32`です) - found type `std::result::Result` - (実際の型は`std::result::Result`です) -``` - - - -これにより、`File::open`関数の戻り値の型は、`Result`であることがわかります。ジェネリック引数の`T`は、 -ここでは成功値の型`std::fs::File`で埋められていて、これはファイルハンドルです。 +`File::open`の戻り値の型は、`Result`です。ジェネリック引数の`T`は、 +`File::open`の実装によって成功値の型`std::fs::File`で埋められていて、これはファイルハンドルです。 エラー値で使用されている`E`の型は、`std::io::Error`です。 - - - この戻り値型は、`File::open`の呼び出しが成功し、読み込みと書き込みを行えるファイルハンドルを返す可能性があることを意味します。 また、関数呼び出しは失敗もする可能性があります: 例えば、ファイルが存在しない可能性、ファイルへのアクセス権限がない可能性です。 `File::open`には成功したか失敗したかを知らせる方法とファイルハンドルまたは、エラー情報を与える方法が必要なのです。 この情報こそが`Result` enumが伝達するものなのです。 -`File::open`が成功した場合、変数`f`の値はファイルハンドルを含む`Ok`インスタンスになります。 -失敗した場合には、発生したエラーの種類に関する情報をより多く含む`Err`インスタンスが`f`の値になります。 +`File::open`が成功した場合、変数`greeting_file_result`の値はファイルハンドルを含む`Ok`インスタンスになります。 +失敗した場合には、発生したエラーの種類に関する情報をより多く含む`Err`インスタンスが`greeting_file_result`の値になります。 -`Option` enumのように、`Result` enumとその列挙子は、初期化処理でインポートされているので、 +`Option` enumのように、`Result` enumとその列挙子は、preludeでスコープ内に持ち込まれているので、 `match`アーム内で`Ok`と`Err`列挙子の前に`Result::`を指定する必要がないことに注目してください。 -ここでは、結果が`Ok`の時に、`Ok`列挙子から中身の`file`値を返すように指示し、 -それからそのファイルハンドル値を変数`f`に代入しています。`match`の後には、 -ファイルハンドルを使用して読み込んだり書き込むことができるわけです。 +このコードは、結果が`Ok`の場合は、`Ok`列挙子から中身の`file`値を返し、 +それからそのファイルハンドル値を変数`greeting_file`に代入しています。 +`match`の後には、ファイルハンドルを使用して読み込んだり書き込むことができるわけです。 -リスト9-4のコードは、`File::open`が失敗した理由にかかわらず`panic!`します。代わりにしたいことは、 -失敗理由によって動作を変えることです: ファイルが存在しないために`File::open`が失敗したら、 +リスト9-4のコードは、`File::open`が失敗した理由にかかわらず`panic!`します。 +ですが、失敗理由によって動作を変えたいとしましょう: ファイルが存在しないために`File::open`が失敗したら、 ファイルを作成し、その新しいファイルへのハンドルを返したいです。他の理由(例えばファイルを開く権限がなかったなど)で、 `File::open`が失敗したら、リスト9-4のようにコードには`panic!`してほしいのです。 -リスト9-5を眺めてください。ここでは`match`に別のアームを追加しています。 +このために、リスト9-5で示すように内側の`match`式を追加します。 ```rust,ignore -use std::fs::File; -use std::io::ErrorKind; - -fn main() { - let f = File::open("hello.txt"); - - let f = match f { - Ok(file) => file, - Err(ref error) if error.kind() == ErrorKind::NotFound => { - match File::create("hello.txt") { - Ok(fc) => fc, - Err(e) => { - panic!( - //ファイルを作成しようとしましたが、問題がありました - "Tried to create file but there was a problem: {:?}", - e - ) - }, - } - }, - Err(error) => { - panic!( - "There was a problem opening the file: {:?}", - error - ) - }, - }; -} +{{#rustdoc_include ../listings/ch09-error-handling/listing-09-05/src/main.rs}} ``` `File::open`が`Err`列挙子に含めて返す値の型は、`io::Error`であり、これは標準ライブラリで提供されている構造体です。 この構造体には、呼び出すと`io::ErrorKind`値が得られる`kind`メソッドがあります。`io::ErrorKind`というenumは、 標準ライブラリで提供されていて、`io`処理の結果発生する可能性のある色々な種類のエラーを表す列挙子があります。 使用したい列挙子は、`ErrorKind::NotFound`で、これは開こうとしているファイルがまだ存在しないことを示唆します。 +そこで、`greeting_file_result`に対してマッチし、さらに`error.kind()`に対する内側のマッチも持たせています。 - -`if error.kind() == ErrorKind::Notfound`という条件式は、*マッチガード*と呼ばれます: -アームのパターンをさらに洗練する`match`アーム上のおまけの条件式です。この条件式は、 -そのアームのコードが実行されるには真でなければいけないのです; そうでなければ、 -パターンマッチングは継続し、`match`の次のアームを考慮します。パターンの`ref`は、 -`error`がガード条件式にムーブされないように必要ですが、ただ単にガード式に参照されます。 -`ref`を使用して`&`の代わりにパターン内で参照を作っている理由は、第18章で詳しく講義します。 -手短に言えば、パターンの文脈において、`&`は参照にマッチし、その値を返しますが、 -`ref`は値にマッチし、それへの参照を返すということなのです。 - - -マッチガードで精査したい条件は、`error.kind()`により返る値が、`ErrorKind` enumの`NotFound`列挙子であるかということです。 +内側のマッチで精査したい条件は、`error.kind()`により返る値が、`ErrorKind` enumの`NotFound`列挙子であるかということです。 もしそうなら、`File::create`でファイル作成を試みます。ところが、`File::create`も失敗する可能性があるので、 -内部にも`match`式を追加する必要があるのです。ファイルが開けないなら、異なるエラーメッセージが出力されるでしょう。 -外側の`match`の最後のアームは同じままなので、ファイルが存在しないエラー以外ならプログラムはパニックします。 +内側の`match`式の2番目のアームが必要なのです。ファイルを作成できない場合、異なるエラーメッセージが出力されます。 +外側の`match`の2番目のアームは同じままなので、ファイルが存在しないエラー以外ならプログラムはパニックします。 + + + +> ### `Result`に対する`match`の使用の代わりとなる方法 +> +> `match`がたくさん出てきましたね!`match`式は非常に有用ですが、非常に原始的でもあります。 +> 第13章でクロージャについて学習しますが、これは`Result`上に定義されているメソッドの多くで使用することができます。 +> コード内で`Result`値を扱うときには、こうしたメソッドを使ったほうがより簡潔になります。 +> +> 例えば、以下はリスト9-5に示したものと同じロジックを書く例ですが、 +> 今度はクロージャと`unwrap_or_else`メソッドを使用しています: +> +> ```rust,ignore +> use std::fs::File; +> use std::io::ErrorKind; +> +> fn main() { +> let greeting_file = File::open("hello.txt").unwrap_or_else(|error| { +> if error.kind() == ErrorKind::NotFound { +> File::create("hello.txt").unwrap_or_else(|error| { +> panic!("Problem creating the file: {:?}", error); +> }) +> } else { +> panic!("Problem opening the file: {:?}", error); +> } +> }); +> } +> ``` +> +> このコードはリスト9-5と同じ動作をしますが、`match`式をまったく含んでおらず、より読みやすいです。 +> 第13章を読み終えたら、この例に戻ってきて、標準ライブラリドキュメント内で`unwrap_or_else`を探してみてください。 +> エラーに対処するときには、これらのメソッドを多用することで、巨大なネストされた`match`式を整理することができます。 `match`の使用は、十分に仕事をしてくれますが、いささか冗長になり得る上、必ずしも意図をよく伝えるとは限りません。 -`Result`型には、色々な作業をするヘルパーメソッドが多く定義されています。それらの関数の一つは、 -`unwrap`と呼ばれますが、リスト9-4で書いた`match`式と同じように実装された短絡メソッドです。 +`Result`型には、様々な特定の作業をするヘルパーメソッドが多く定義されています。 +`unwrap`メソッドは、リスト9-4で書いた`match`式と同じように実装された短絡メソッドです。 `Result`値が`Ok`列挙子なら、`unwrap`は`Ok`の中身を返します。`Result`が`Err`列挙子なら、 `unwrap`は`panic!`マクロを呼んでくれます。こちらが実際に動作している`unwrap`の例です: @@ -387,11 +342,7 @@ call the `panic!` macro for us. Here is an example of `unwrap` in action: ファイル名: src/main.rs ```rust,should_panic -use std::fs::File; - -fn main() { - let f = File::open("hello.txt").unwrap(); -} +{{#rustdoc_include ../listings/ch09-error-handling/no-listing-04-unwrap/src/main.rs}} ``` + + このコードを*hello.txt*ファイルなしで走らせたら、`unwrap`メソッドが行う`panic!`呼び出しからのエラーメッセージを目の当たりにするでしょう: ```text -thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { -repr: Os { code: 2, message: "No such file or directory" } }', -src/libcore/result.rs:906:4 -('main'スレッドは、src/libcore/result.rs:906:4の -「`Err`値に対して`Result::unwrap()`が呼び出されました: Error{ -repr: Os { code: 2, message: "そのようなファイルまたはディレクトリはありません" } }」でパニックしました) +thread 'main' panicked at src/main.rs:4:49: +called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" } +('main'スレッドは、src/main.rs:4:49でパニックしました: +`Err`値に対して`Result::unwrap()`が呼び出されました: Os { code: 2, kind: NotFound, message: "そのようなファイルやディレクトリはありません" }) ``` -別のメソッド`expect`は、`unwrap`に似ていますが、`panic!`のエラーメッセージも選択させてくれます。 +同様に、`expect`メソッドは、`panic!`のエラーメッセージも選択させてくれます。 `unwrap`の代わりに`expect`を使用して、いいエラーメッセージを提供すると、意図を伝え、 パニックの原因をたどりやすくしてくれます。`expect`の表記はこんな感じです: @@ -428,12 +383,7 @@ panic easier. The syntax of `expect` looks like this: ファイル名: src/main.rs ```rust,should_panic -use std::fs::File; - -fn main() { - // hello.txtを開くのに失敗しました - let f = File::open("hello.txt").expect("Failed to open hello.txt"); -} +{{#rustdoc_include ../listings/ch09-error-handling/no-listing-05-expect/src/main.rs}} ``` + + `expect`を`unwrap`と同じように使用してます: ファイルハンドルを返したり、`panic!`マクロを呼び出しています。 `expect`が`panic!`呼び出しで使用するエラーメッセージは、`unwrap`が使用するデフォルトの`panic!`メッセージではなく、 `expect`に渡した引数になります。以下のようになります: ```text -thread 'main' panicked at 'Failed to open hello.txt: Error { repr: Os { code: -2, message: "No such file or directory" } }', src/libcore/result.rs:906:4 +thread 'main' panicked at src/main.rs:5:10: +hello.txt should be included in this project: Os { code: 2, kind: NotFound, message: "No such file or directory" } +('main'スレッドは、src/main.rs:5:10でパニックしました: +「hello.txtがこのプロジェクトに含まれているべきです: Os { code: 2, kind: NotFound, message: "そのようなファイルやディレクトリはありません" }) ``` -このエラーメッセージは、指定したテキストの`hello.txtを開くのに失敗しました`で始まっているので、 -コード内のどこでエラーメッセージが出力されたのかより見つけやすくなるでしょう。複数箇所で`unwrap`を使用していたら、 -ズバリどの`unwrap`がパニックを引き起こしているのか理解するのは、より時間がかかる可能性があります。 -パニックする`unwrap`呼び出しは全て、同じメッセージを出力するからです。 +製品レベルの品質のコードでは、多くのRustaceanは`unwrap`よりむしろ`expect`を選択し、 +なぜその操作が常に成功すると想定されるのかについてより多くの文脈情報を提供します。 +そうすることで、万一あなたの仮定が誤っていたと判明した場合には、 +デバッグ時に利用するためのより多くの情報が得られます。 -失敗する可能性のある何かを呼び出す実装をした関数を書く際、関数内でエラーを処理する代わりに、 +関数の実装が失敗する可能性のある何かを呼び出す際、その関数自体の中でエラーを処理する代わりに、 呼び出し元がどうするかを決められるようにエラーを返すことができます。これはエラーの*委譲*として認知され、 自分のコードの文脈で利用可能なものよりも、 エラーの処理法を規定する情報やロジックがより多くある呼び出し元のコードに制御を明け渡します。 @@ -488,7 +445,7 @@ handled than what you have available in the context of your code. 例えば、リスト9-6の関数は、ファイルからユーザ名を読み取ります。ファイルが存在しなかったり、読み込みできなければ、 @@ -500,26 +457,12 @@ to the code that called this function. ファイル名: src/main.rs -```rust -use std::io; -use std::io::Read; -use std::fs::File; - -fn read_username_from_file() -> Result { - let f = File::open("hello.txt"); - - let mut f = match f { - Ok(file) => file, - Err(e) => return Err(e), - }; + - let mut s = String::new(); - - match f.read_to_string(&mut s) { - Ok(_) => Ok(s), - Err(e) => Err(e), - } -} +```rust +{{#include ../listings/ch09-error-handling/listing-09-06/src/main.rs:here}} ``` + +この関数はもっと短く書くことができますが、エラー処理について詳しく見るために、 +まずはエラー処理をたくさん手動で書くことから始めましょう; より短い方法は最後に示します。 +まずは、関数の戻り値型に注目しましょう: `Result`です。つまり、この関数は、 +`Result`型の値を返しているということです。ここでジェネリック引数の`T`は、具体型`String`で埋められ、 +ジェネリック引数の`E`は具体型`io::Error`で埋められています。 + + -まずは、関数の戻り値型に注目してください: `Result`です。つまり、この関数は、 -`Result`型の値を返しているということです。ここでジェネリック引数の`T`は、具体型`String`で埋められ、 -ジェネリック引数の`E`は具体型`io::Error`で埋められています。この関数が何の問題もなく成功すれば、 +この関数が何の問題もなく成功すれば、 この関数を呼び出したコードは、`String`(関数がファイルから読み取ったユーザ名)を保持する`Ok`値を受け取ります。 この関数が何か問題に行き当たったら、呼び出し元のコードは`io::Error`のインスタンスを保持する`Err`値を受け取り、 この`io::Error`は問題の内容に関する情報をより多く含んでいます。関数の戻り値の型に`io::Error`を選んだのは、 @@ -556,51 +509,57 @@ function and the `read_to_string` method. -関数の本体は、`File::open`関数を呼び出すところから始まります。そして、リスト9-4の`match`に似た`match`で返ってくる`Result`値を扱い、 -`Err`ケースに`panic!`を呼び出すだけの代わりに、この関数から早期リターンしてこの関数のエラー値として、 -`File::open`から得たエラー値を呼び出し元に渡し戻します。`File::open`が成功すれば、 -ファイルハンドルを変数`f`に保管して継続します。 +関数の本体は、`File::open`関数を呼び出すところから始まります。 +そして、リスト9-4の`match`に似た`match`で`Result`値を扱います。 +`File::open`が成功すれば、パターン変数`file`にあるファイルハンドルは可変変数`username_file`内の値となり、 +関数は継続します。 +`Err`ケースでは`panic!`を呼び出す代わりに、関数から完全に早期リターンしてこの関数のエラー値として、 +`File::open`から得たエラー値、これはパターン変数`e`内にありますが、これを呼び出し元に渡し戻すために`return`キーワードを使用します。 -さらに、変数`s`に新規`String`を生成し、`f`のファイルハンドルに対して`read_to_string`を呼び出して、 -ファイルの中身を`s`に読み出します。`File::open`が成功しても、失敗する可能性があるので、`read_to_string`メソッドも、 +`username_file`にファイルハンドルが得られたら、関数は次に変数`username`に新規`String`を生成し、 +`username_file`のファイルハンドルに対して`read_to_string`を呼び出して、ファイルの中身を`username`に読み出します。 +`File::open`が成功しても、失敗する可能性があるので、`read_to_string`メソッドも、 `Result`を返却します。その`Result`を処理するために別の`match`が必要になります: `read_to_string`が成功したら、 -関数は成功し、今は`Ok`に包まれた`s`に入っているファイルのユーザ名を返却します。`read_to_string`が失敗したら、 +関数は成功し、今は`Ok`に包まれた`username`に入っているファイルのユーザ名を返却します。`read_to_string`が失敗したら、 `File::open`の戻り値を扱った`match`でエラー値を返したように、エラー値を返します。 しかし、明示的に`return`を述べる必要はありません。これが関数の最後の式だからです。 そうしたら、呼び出し元のコードは、ユーザ名を含む`Ok`値か、`io::Error`を含む`Err`値を得て扱います。 -呼び出し元のコードがそれらの値をどうするかはわかりません。呼び出しコードが`Err`値を得たら、 +それらの値をどうするかを決めるのは、呼び出し元のコードに委ねられます。呼び出しコードが`Err`値を得たら、 例えば、`panic!`を呼び出してプログラムをクラッシュさせたり、デフォルトのユーザ名を使ったり、 ファイル以外の場所からユーザ名を検索したりできるでしょう。呼び出し元のコードが実際に何をしようとするかについて、 十分な情報がないので、成功や失敗情報を全て委譲して適切に扱えるようにするのです。 @@ -613,19 +572,19 @@ question mark operator `?` to make this easier. Rustにおいて、この種のエラー委譲は非常に一般的なので、Rustにはこれをしやすくする`?`演算子が用意されています。 #### エラー委譲のショートカット: `?`演算子 -リスト9-7もリスト9-6と同じ機能を有する`read_username_from_file`の実装ですが、 -こちらは`?`演算子を使用しています: +リスト9-7はリスト9-6にあったのと同じ機能を持つ`read_username_from_file`の実装ですが、 +こちらは`?`演算子を使用しています。 + ```rust -use std::io; -use std::io::Read; -use std::fs::File; - -fn read_username_from_file() -> Result { - let mut f = File::open("hello.txt")?; - let mut s = String::new(); - f.read_to_string(&mut s)?; - Ok(s) -} +{{#include ../listings/ch09-error-handling/listing-09-07/src/main.rs:here}} ``` `Result`値の直後に置かれた`?`は、リスト9-6で`Result`値を処理するために定義した`match`式とほぼ同じように動作します。 `Result`の値が`Ok`なら、`Ok`の中身がこの式から返ってきて、プログラムは継続します。値が`Err`なら、 -`return`キーワードを使ったかのように関数全体から`Err`の中身が返ってくるので、 +`return`キーワードを使ったかのように関数全体から`Err`が返ってくるので、 エラー値は呼び出し元のコードに委譲されます。 -リスト9-6の`match`式と`?`演算子には違いがあります: `?`を使ったエラー値は、 -標準ライブラリの`From`トレイトで定義され、エラーの型を別のものに変換する`from`関数を通ることです。 +リスト9-6の`match`式がやっていることと`?`演算子がやっていることには、違いがあります: +`?`演算子が呼ばれる対象となったエラー値は、 +標準ライブラリの`From`トレイトで定義され、値を別の型に変換する`from`関数を通ることです。 `?`演算子が`from`関数を呼び出すと、受け取ったエラー型が現在の関数の戻り値型で定義されているエラー型に変換されます。これは、 個々がいろんな理由で失敗する可能性があるのにも関わらず、関数が失敗する可能性を全て一つのエラー型で表現して返す時に有用です。 -各エラー型が`from`関数を実装して返り値のエラー型への変換を定義している限り、 -`?`演算子が変換の面倒を自動的に見てくれます。 + + + +例えば、リスト9-7の`read_username_from_file`関数を、`OurError`という名前の自分で定義したカスタムエラー型を返すように変更することができます。 +さらに、`io::Error`から`OutError`のインスタンスを構築するための`impl From for OurError`を定義すれば、 +`read_username_from_file`の本体の中の`?`演算子呼び出しは`from`を呼び出してくれるので、 +関数にコードを追加する必要なくエラー型を変換してくれます。 -リスト9-7の文脈では、`File::open`呼び出し末尾の`?`は`Ok`の中身を変数`f`に返します。 +リスト9-7の文脈では、`File::open`呼び出し末尾の`?`は`Ok`の中身を変数`username_file`に返します。 エラーが発生したら、`?`演算子により関数全体から早期リターンし、あらゆる`Err`値を呼び出し元に与えます。 同じ法則が`read_to_string`呼び出し末尾の`?`にも適用されます。 @@ -715,18 +681,12 @@ method calls immediately after the `?`, as shown in Listing 9-8. ファイル名: src/main.rs -```rust -use std::io; -use std::io::Read; -use std::fs::File; - -fn read_username_from_file() -> Result { - let mut s = String::new(); + - File::open("hello.txt")?.read_to_string(&mut s)?; - - Ok(s) -} +```rust +{{#include ../listings/ch09-error-handling/listing-09-08/src/main.rs:here}} ``` -`s`の新規`String`の生成を関数の冒頭に移動しました; その部分は変化していません。変数`f`を生成する代わりに、 +`username`の新規`String`の生成を関数の冒頭に移動しました; その部分は変化していません。 +変数`username_file`を生成する代わりに、 `read_to_string`の呼び出しを直接`File::open("hello.txt")?`の結果に連結させました。 それでも、`read_to_string`呼び出しの末尾には`?`があり、`File::open`と`read_to_string`両方が成功したら、 -エラーを返すというよりもそれでも、`s`にユーザ名を含む`Ok`値を返します。機能もまたリスト9-6及び、9-7と同じです; +エラーを返すというよりもそれでも、`username`を含む`Ok`値を返します。機能もまたリスト9-6及び、9-7と同じです; ただ単に異なるバージョンのよりエルゴノミックな書き方なのです。 -#### `?`演算子は、`Result`を返す関数でしか使用できない +これを`fs::read_to_string`を使用してさらに短くする方法をリスト9-9に示します。 -`?`演算子は戻り値に`Result`を持つ関数でしか使用できません。というのも、リスト9-6で定義した`match`式と同様に動作するよう、 -定義されているからです。`Result`の戻り値型を要求する`match`の部品は、`return Err(e)`なので、 -関数の戻り値はこの`return`と互換性を保つために`Result`でなければならないのです。 +ファイル名: src/main.rs + + + +```rust +{{#include ../listings/ch09-error-handling/listing-09-09/src/main.rs:here}} +``` -`main`関数で`?`演算子を使用したらどうなるか見てみましょう。`main`関数は、戻り値が`()`でしたね: +リスト9-9: ファイルを開いて読む代わりに`fs::read_to_string`を使用する -```rust,ignore -use std::fs::File; + -fn main() { - let f = File::open("hello.txt")?; -} +ファイルを文字列に読み込むことは非常によくある操作なので、標準ライブラリは、 +ファイルを開き、新しい`String`を作成し、ファイルの内容を読み込み、内容をその`String`に格納し、それを返す、 +便利な`fs::read_to_string`関数を提供しています。そうそう、`fs::read_to_string`を使用してしまうと、 +エラー処理のすべてについて説明する機会がなくなってしまうので、長ったらしい方法を先に使ったのでした。 + + + +#### `?`演算子が使用できる場所 + + + +`?`演算子は、`?`を使用する対象の値と戻り値の型に互換性がある関数でしか使用できません。 +というのも`?`演算子は、リスト9-6で定義した`match`式と同様に関数から値の早期リターンを実行するように定義されているからです。 +リスト9-6では、`match`は`Result`値を使用して、早期リターンする側のアームは`Err(e)`値を返していました。 +関数の戻り値型はこの`return`と互換性を保てるように、`Result`でなければならないのです。 + + + +リスト9-10で、`?`を使用する対象の値の型と戻り値の型に互換性がない`main`関数で、 +`?`演算子を使用した場合に得られるエラーを見てみましょう: + + + +ファイル名: src/main.rs + +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch09-error-handling/listing-09-10/src/main.rs}} ``` + +リスト9-10: `()`を返す`main`関数内で`?`を使用しようとするとコンパイルが通らない + + +このコードはファイルを開きますが、これは失敗する可能性があります。 +`?`演算子は`File::open`によって返される`Result`値を確認して対処しますが、この`main`関数は`Result`ではなく`()`の戻り値型を持っています。 このコードをコンパイルすると、以下のようなエラーメッセージが得られます: -```text -error[E0277]: the trait bound `(): std::ops::Try` is not satisfied -(エラー: `(): std::ops::Try`というトレイト境界が満たされていません) - --> src/main.rs:4:13 - | -4 | let f = File::open("hello.txt")?; - | ------------------------ - | | - | the `?` operator can only be used in a function that returns - `Result` (or another type that implements `std::ops::Try`) - | in this macro invocation - | (このマクロ呼び出しの`Result`(かまたは`std::ops::Try`を実装する他の型)を返す関数でしか`?`演算子は使用できません) - | - = help: the trait `std::ops::Try` is not implemented for `()` - (助言: `std::ops::Try`トレイトは`()`には実装されていません) - = note: required by `std::ops::Try::from_error` - (注釈: `std::ops::Try::from_error`で要求されています) +```console +{{#include ../listings/ch09-error-handling/listing-09-10/output.txt}} ``` + +このエラーは、`?`演算子は`Result`、`Option`、またはその他`FromResidual`を実装する型を返す関数でしか使用が許可されないと指摘しています。 + + + +このエラーを修正する方法としては、二つの選択肢があります。 +一つは、それを阻害する制限がない場合は、関数の戻り値型を、`?`演算子を使用する対象の値と互換性があるような型に変更することです。 +もう一つの手法は、`match`または`Result`のメソッドのいずれかを使用して、何らかの適切な方法で`Result`を処理することです。 + + + +エラーメッセージは、`?`は`Option`値にも使用できることに言及しています。 +`Result`に`?`を使用する場合と同様に、`Option`を返す関数の中でのみ、`Option`に`?`を使用することができます。 +`Option`に対して呼ばれた場合の`?`演算子の挙動は、`Result`に対して呼ばれた場合の挙動と似ています: +もしその値が`None`ならば、その時点で`None`が関数から早期リターンされます。 +もしその値が`Some`ならば、`Some`の内側の値がその式の結果の値となり、関数は継続します。 +リスト9-11は、与えられたテキストの最初の行の最後の文字を探索する関数の例です: + +```rust +{{#rustdoc_include ../listings/ch09-error-handling/listing-09-11/src/main.rs:here}} +``` + + + +リスト9-11: `Option`値に対する`?`演算子の使用 + + + +この関数は、文字はあるかもしれないし、ないかもしれないので、`Option`を返します。 +このコードは`text`文字列スライス引数を受け取り、それに対して`lines`メソッドを呼び出します。 +これは文字列内の行を走査するイテレータを返します。この関数では最初の行を確認したいので、 +イテレータに対して`next`を呼び出してイテレータから最初の値を取得します。 +`text`が空文字列の場合は、この`next`呼び出しは`None`を返すでしょう。 +その場合は`?`を使用して停止し、`last_char_of_first_line`から`None`を返します。 +`text`が空文字列でない場合は、`next`は`text`内の最初の行の文字列スライスを含む`Some`値を返すでしょう。 + + + +`?`が文字列スライスを抽出するので、その文字列スライスに対して`chars`を呼び出して、含まれる文字からなるイテレータを得ることができます。 +最初の行の最後の文字に関心があるので、このイテレータの最後の要素を返すために`last`を呼び出します。 +例えば`text`が空行で始まるが他の行には文字が含まれる`"\nhi"`のような文字列の場合、 +最初の行が空文字列である可能性があるので、この戻り値は`Option`になっています。 +しかしながら、最初の行の最後の文字がある場合は、それを`Some`列挙子に入れて返します。 +中間の`?`演算子はこのロジックを簡潔に表現する方法を提供し、そのためこの関数を一行で実装することができています。 +もし`?`演算子が`Option`に使用できなかったなら、より多くのメソッド呼び出しや`match`式を使用してこのロジックを実装する必要があったでしょう。 + + + +`Result`を返す関数内では`Result`に対して`?`演算子を使用でき、`Option`を返す関数内では`Option`に対して`?`演算子を使用できますが、 +混ぜて組み合わせることはできないことに注意してください。 +`?`演算子は、`Result`を`Option`に、またはその逆に、自動的に変換することはしません; +そのような場合には明示的に変換を行うために、`Result`の`ok`メソッドや、`Option`の`ok_or`メソッドのようなメソッドを使用することができます。 + + + +今までに使ってきた`main`関数はすべて`()`を返してきました。 +`main`関数は、実行可能なプログラムの開始および終了点であることから特別扱いされており、 +プログラムが期待通りに振る舞うために、その戻り値型として指定できる型に制限があります。 + + + +幸運なことに、`main`は`Result<(), E>`を返すこともできます。 +リスト9-12はリスト9-10のコードを含んでいますが、`main`の戻り値型を`Result<(), Box>`に変更し、 +最後に戻り値`Ok(())`を追加しています。 +これでこのコードはコンパイルできるでしょう: + +```rust,ignore +{{#rustdoc_include ../listings/ch09-error-handling/listing-09-12/src/main.rs}} +``` + + + +リスト9-12: `Result<(), E>`を返すように`main`を変更することで、`Result`値に対する`?`演算子が使用可能になる + + -このエラーは、`?`演算子は`Result`を返す関数でしか使用が許可されないと指摘しています。 `Result`を返さない関数では、`Result`を返す別の関数を呼び出した時、 `?`演算子を使用してエラーを呼び出し元に委譲する可能性を生み出す代わりに、`match`か`Result`のメソッドのどれかを使う必要があるでしょう。 + + +`Box`型は*トレイトオブジェクト*ですが、これについては第17章の[「トレイトオブジェクトで異なる型の値を許容する」][trait-objects]節で話します。 +今のところは、`Box`は「任意の種類のエラー」を意味するものと理解してください。 +エラー型`Box`を持つ`main`関数の中では、任意の`Err`値を早期リターンすることができるので、`Result`値に対する`?`の使用が許可されます。 +この`main`関数の本体は型`std::io::Error`のエラーしか返しませんが、それでも`Box`を指定することにより、 +他のエラーを返すコードが`main`の本体に追加された場合であっても、このシグネチャは正しいままであり続けるでしょう。 + + + +`main`関数が`Result<(), E>`を返す場合、その実行可能ファイルは、 +`main`が`Ok(())`を返す場合には値`0`で終了し、`main`が`Err`値を返す場合は非ゼロ値で終了するでしょう。 +Cで書かれた実行可能ファイルは終了時に整数を返します: +正常終了するプログラムは整数`0`を返し、エラーが発生したプログラムは`0`以外の整数を返します。 +Rustもこの慣例に従い、実行可能ファイルから整数を返します。 + + + +`main`関数は[`std::process::Termination`トレイト][termination]を実装する任意の型を返すことができます。 +このトレイトには`ExitCode`を返す`report`関数が含まれます。 +自身の型に対する`Termination`トレイトの実装に関するさらなる情報については、 +標準ライブラリドキュメントを確認してください。 + + +[handle_failure]: ch02-00-guessing-game-tutorial.html#resultで失敗の可能性を扱う +[trait-objects]: ch17-02-trait-objects.html#トレイトオブジェクトで異なる型の値を許容する +[termination]: https://doc.rust-lang.org/std/process/trait.Termination.html diff --git a/src/ch09-03-to-panic-or-not-to-panic.md b/src/ch09-03-to-panic-or-not-to-panic.md index 0aca603ba..91f59d6fd 100644 --- a/src/ch09-03-to-panic-or-not-to-panic.md +++ b/src/ch09-03-to-panic-or-not-to-panic.md @@ -5,39 +5,36 @@ ## `panic!`すべきかするまいか -では、`panic!`すべき時と`Result`を返すべき時はどう決定すればいいのでしょうか?コードがパニックしたら、 +では、`panic!`を呼ぶべき時と`Result`を返すべき時はどう決定すればいいのでしょうか?コードがパニックしたら、 回復する手段はありません。回復する可能性のある手段の有る無しに関わらず、どんなエラー場面でも`panic!`を呼ぶことはできますが、 -そうすると、呼び出す側のコードの立場に立ってこの場面は回復不能だという決定を下すことになります。 -`Result`値を返す決定をすると、決断を下すのではなく、呼び出し側に選択肢を与えることになります。 +そうすると、呼び出す側のコードに代わってこの場面は回復不能だという決定を下すことになります。 +`Result`値を返す決定をすると、呼び出し側に選択肢を与えることになります。 呼び出し側は、場面に合わせて回復を試みることを決定したり、この場合の`Err`値は回復不能と断定して、 `panic!`を呼び出し、回復可能だったエラーを回復不能に変換することもできます。故に、`Result`を返却することは、 失敗する可能性のある関数を定義する際には、いい第一選択肢になります。 -稀な場面では、`Result`を返すよりもパニックするコードを書く方がより適切になることもあります。 -例やプロトタイプコード、テストでパニックするのが適切な理由を探ってみましょう。 -それからコンパイラではありえない失敗だと気づけなくとも、人間なら気づける場面を議論しましょう。 +例やプロトタイプコード、テストなどの場面では、`Result`を返すよりもパニックするコードを書く方がより適切になることもあります。 +その理由を探ってみて、それからコンパイラではありえない失敗だと気づけなくとも、人間なら気づける場面を議論しましょう。 そして、ライブラリコードでパニックするか決定する方法についての一般的なガイドラインで結論づけましょう。 -例を記述して何らかの概念を具体化している時、頑健なエラー処理コードも例に含むことは、例の明瞭さを欠くことになりかねません。 +例を記述して何らかの概念を具体化している時、頑健なエラー処理コードを含めることは、例の明瞭さを欠くことになりかねません。 例において、`unwrap`などのパニックする可能性のあるメソッド呼び出しは、 アプリケーションにエラーを処理してほしい方法へのプレースホルダーを意味していると理解され、 これは残りのコードがしていることによって異なる可能性があります。 @@ -69,7 +66,7 @@ your code for when you’re ready to make your program more robust. 非常に便利です。それらにより、コードにプログラムをより頑健にする時の明らかなマーカーが残されるわけです。 -`Result`が`Ok`値であると確認する何らかの別のロジックがある場合、`unwrap`を呼び出すことは適切でしょうが、 +`Result`が`Ok`値であることを保証する何らかの別のロジックがある場合、`unwrap`または`except`を呼び出すことは適切でしょうが、 コンパイラは、そのロジックを理解はしません。それでも、処理する必要のある`Result`は存在するでしょう: 呼び出している処理が何であれ、自分の特定の場面では論理的に起こり得なくても、一般的にまだ失敗する可能性はあるわけです。 手動でコードを調査して`Err`列挙子は存在しないと確認できたら、`unwrap`を呼び出すことは完全に受容できることです。 +決して`Err`列挙子にならないと考える理由を`expect`のテキストに文書化すると、さらに良いでしょう。 こちらが例です: ```rust -use std::net::IpAddr; - -let home: IpAddr = "127.0.0.1".parse().unwrap(); +{{#rustdoc_include ../listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/src/main.rs:here}} ``` ハードコードされた文字列を構文解析することで`IpAddr`インスタンスを生成しています。 -プログラマには`127.0.0.1`が合法なIPアドレスであることがわかるので、ここで`unwrap`を使用することは、 +プログラマには`127.0.0.1`が合法なIPアドレスであることがわかるので、ここで`expect`を使用することは、 受容可能なことです。しかしながら、ハードコードされた合法な文字列が存在することは、 `parse`メソッドの戻り値型を変えることにはなりません: それでも得られるのは、`Result`値であり、 -コンパイラはまだ`Err`列挙子になる可能性があるかのように`Result`を処理することを強制してきます。 +コンパイラは`Err`列挙子になる可能性があるかのように`Result`を処理することを強制してきます。 コンパイラは、この文字列が常に合法なIPアドレスであると把握できるほど利口ではないからです。 プログラムにハードコードされるのではなく、IPアドレス文字列がユーザ起源でそれ故に*確かに*失敗する可能性がある場合、 `Result`をもっと頑健な方法で処理したほうが絶対にいいでしょう。 +このIPアドレスはハードコードされたものだという想定に言及することで、もし将来IPアドレスを他の情報源から取得する必要がでてきた場合、 +`expect`の部分をよりよいエラー処理コードに変更することが促されるでしょう。 -コードが悪い状態に陥る可能性があるときにパニックさせるのは、推奨されることです。この文脈において、 -*悪い状態*とは、何らかの前提、保証、契約、不変性が破られたことを言い、例を挙げれば、無効な値、 -矛盾する値、行方不明な値がコードに渡されることと、さらに以下のいずれか一つ以上の状態であります: +コードが悪い状態に陥る可能性があるときには、パニックさせることが推奨されます。 +この文脈での*悪い状態*とは、無効な値、矛盾する値、欠けた値が自身のコードに渡されるなど、何らかの仮定、保証、契約、不変条件が破られることに加え、 +以下のいずれか一つ以上に当てはまる状態のことです: -* 悪い状態がときに起こるとは*予想*されないとき。 -* この時点以降、この悪い状態にないことを頼りにコードが書かれているとき。 -* 使用している型にこの情報をコード化するいい手段がないとき。 +* 悪い状態は、予期されていない何かです。ユーザが誤ったフォーマットでデータを入力することなどの、場合によっては起こりうることとは異なります。 +* この時点以降の自身のコードは、各段階で問題が無いか確認するのではなく、この悪い状態にないことに依存する必要があります。 +* 使用している型にこの情報をコード化するいい手段がありません。これが意味するところの例は、第17章の[「状態と振る舞いを型としてコード化する」][encoding]節で取り組みます。 -誰かが自分のコードを呼び出して筋の通らない値を渡してきたら、最善の選択肢は`panic!`し、 +誰かが自分のコードを呼び出して意味をなさない値を渡してきた場合は、可能であれば、 +ライブラリの利用者がその場合にどうしたいのかを決定できるように、エラーを返すのが最もよいでしょう。 +ですが、実行を継続するのが安全でなかったり有害かもしれない場合は、最善の選択肢は`panic!`を呼び出し、 開発段階で修正できるように自分たちのコードにバグがあることをライブラリ使用者に通知することかもしれません。 同様に自分の制御下にない外部コードを呼び出し、修正しようのない無効な状態を返すときに`panic!`はしばしば適切です。 - -しかし、どんなにコードをうまく書いても起こると予想されますが、悪い状態に達したとき、それでも`panic!`呼び出しをするよりも、 -`Result`を返すほうがより適切です。例には、不正なデータを渡されたパーサとか、 -訪問制限に引っかかったことを示唆するステータスを返すHTTPリクエストなどが挙げられます。 -このような場合には、呼び出し側が問題の処理方法を決定できるように`Result`を返してこの悪い状態を委譲して、 -失敗が予想される可能性であることを示唆するべきです。`panic!`を呼び出すことは、 -これらのケースでは最善策ではないでしょう。 - - - -コードが値に対して処理を行う場合、コードはまず値が合法であることを確認し、 +However, when failure is expected, it’s more appropriate to return a `Result` +than to make a `panic!` call. Examples include a parser being given malformed +data or an HTTP request returning a status that indicates you have hit a rate +limit. In these cases, returning a `Result` indicates that failure is an +expected possibility that the calling code must decide how to handle. +--> + +しかしながら、失敗が予測できる場合は、`panic!`呼び出しをするよりも`Result`を返すほうがより適切です。 +その例には、不正なデータを渡されたパーサとか、 +レートリミットに引っかかったことを示唆するステータスを返すHTTPリクエストなどが挙げられます。 +このような場合では`Result`を返すことで、失敗は、呼び出し側が処理方法を決定しなくてはならない、 +予測できる可能性であることが示されます。 + + + +あなたのコードが、不正な値を使用して呼ばれるとユーザを危険に晒すおそれのある処理を行う場合、コードはまず値が合法であることを確認し、 値が合法でなければパニックするべきです。これはほぼ安全性上の理由によるものです: 不正なデータの処理を試みると、 コードを脆弱性に晒す可能性があります。これが、境界外へのメモリアクセスを試みたときに標準ライブラリが`panic!`を呼び出す主な理由です: 現在のデータ構造に属しないメモリにアクセスを試みることは、ありふれたセキュリティ問題なのです。 @@ -217,20 +225,20 @@ documentation for the function. ですが、全ての関数でたくさんのエラーチェックを行うことは冗長で煩わしいことでしょう。幸運にも、 -Rustの型システム(故にコンパイラが行う型精査)を使用して多くの検査を行ってもらうことができます。 +Rustの型システム(故にコンパイラによって行われる型精査)を使用して多くの検査を行ってもらうことができます。 関数の引数に特定の型があるなら、合法な値があるとコンパイラがすでに確認していることを把握して、 コードのロジックに進むことができます。例えば、`Option`以外の型がある場合、プログラムは、 *何もない*ではなく*何かある*と想定します。そうしたらコードは、 @@ -252,7 +260,7 @@ guessing game in Chapter 2 in which our code asked the user to guess a number between 1 and 100. We never validated that the user’s guess was between those numbers before checking it against our secret number; we only validated that the guess was positive. In this case, the consequences were not very dire: our -output of “Too high” or “Too low” would still be correct. It would be a +output of “Too high” or “Too low” would still be correct. But it would be a useful enhancement to guide the user toward valid guesses and have different behavior when a user guesses a number that’s out of range versus when a user types, for example, letters instead. @@ -263,7 +271,7 @@ Rustの型システムを使用して合法な値があると確認するとい コードがユーザに1から100までの数字を推測するよう求めたことを思い出してください。 秘密の数字と照合する前にユーザの推測がそれらの値の範囲にあることを全く確認しませんでした; 推測が正であることしか確認しませんでした。この場合、結果はそれほど悲惨なものではありませんでした: -「大きすぎ」、「小さすぎ」という出力は、それでも正しかったでしょう。ユーザを合法な推測に導き、 +「大きすぎ」、「小さすぎ」という出力は、それでも正しかったでしょう。しかし、ユーザを合法な推測に導き、 ユーザが範囲外の数字を推測したり、例えばユーザが文字を代わりに入力したりしたときに別の挙動をするようにしたら、 有益な改善になるでしょう。 @@ -277,22 +285,7 @@ number being in range, like so: それから数字が範囲に収まっているというチェックを追加することでしょう。そう、以下のように: ```rust,ignore -loop { - // --snip-- - - let guess: i32 = match guess.trim().parse() { - Ok(num) => num, - Err(_) => continue, - }; - - if guess < 1 || guess > 100 { - println!("The secret number will be between 1 and 100."); - continue; - } - - match guess.cmp(&secret_number) { - // --snip-- -} +{{#rustdoc_include ../listings/ch09-error-handling/no-listing-09-guess-out-of-range/src/main.rs:here}} ``` 代わりに、新しい型を作って検証を関数内に閉じ込め、検証を全箇所で繰り返すのではなく、 その型のインスタンスを生成することができます。そうすれば、関数がその新しい型をシグニチャに用い、 -受け取った値を自信を持って使用することは安全になります。リスト9-9に、`new`関数が1から100までの値を受け取った時のみ、 +受け取った値を自信を持って使用することは安全になります。リスト9-13に、`new`関数が1から100までの値を受け取った時のみ、 `Guess`のインスタンスを生成する`Guess`型を定義する一つの方法を示しました。 + + ```rust -pub struct Guess { - value: u32, -} - -impl Guess { - pub fn new(value: u32) -> Guess { - if value < 1 || value > 100 { - // 予想の値は1から100の範囲でなければなりませんが、{}でした - panic!("Guess value must be between 1 and 100, got {}.", value); - } - - Guess { - value - } - } - - pub fn value(&self) -> u32 { - self.value - } -} +{{#include ../listings/ch09-error-handling/listing-09-13/src/main.rs:here}} ``` -リスト9-9: 値が1から100の場合のみ処理を継続する`Guess`型 +リスト9-13: 値が1から100の場合のみ処理を継続する`Guess`型 -まず、`u32`型の`value`をフィールドに持つ`Guess`という名前の構造体を定義しています。 +まず、`i32`型の`value`をフィールドに持つ`Guess`という名前の構造体を定義しています。 ここに数値が保管されます。 それから`Guess`に`Guess`値のインスタンスを生成する`new`という名前の関連関数を実装しています。 -`new`関数は、`u32`型の`value`という引数を取り、`Guess`を返すように定義されています。 +`new`関数は、`i32`型の`value`という引数を取り、`Guess`を返すように定義されています。 `new`関数の本体のコードは、`value`をふるいにかけ、1から100の範囲であることを確かめます。 `value`がふるいに引っかかったら、`panic!`呼び出しを行います。これにより、呼び出しコードを書いているプログラマに、 修正すべきバグがあると警告します。というのも、この範囲外の`value`で`Guess`を生成することは、 @@ -397,17 +376,17 @@ to the `value` parameter and return the `Guess`. -次に、`self`を借用し、他に引数はなく、`u32`を返す`value`というメソッドを実装します。 +次に、`self`を借用し、他に引数はなく、`i32`を返す`value`というメソッドを実装します。 この類のメソッドは時に*ゲッター*と呼ばれます。目的がフィールドから何らかのデータを得て返すことだからです。 この公開メソッドは、`Guess`構造体の`value`フィールドが非公開なので、必要になります。 `value`フィールドが非公開なことは重要であり、そのために`Guess`構造体を使用するコードは、 @@ -417,11 +396,11 @@ hasn’t been checked by the conditions in the `Guess::new` function. -そうしたら、引数を一つ持つか、1から100の範囲の数値のみを返す関数は、シグニチャで`u32`ではなく、 +そうしたら、引数を一つ持つか、1から100の範囲の数値のみを返す関数は、シグニチャで`i32`ではなく、 `Guess`を取るか返し、本体内で追加の確認を行う必要はなくなると宣言できるでしょう。 + +[encoding]: ch17-03-oo-design-patterns.html#状態と振る舞いを型としてコード化する diff --git a/src/ch10-00-generics.md b/src/ch10-00-generics.md index dc40f97c7..7aa347db7 100644 --- a/src/ch10-00-generics.md +++ b/src/ch10-00-generics.md @@ -6,20 +6,21 @@ -全てのプログラミング言語には、概念の重複を効率的に扱う道具があります。Rustにおいて、そのような道具の一つが*ジェネリクス*です。 -ジェネリクスは、具体型や他のプロパティの抽象的な代役です。コード記述の際、コンパイルやコード実行時に、 +全てのプログラミング言語には、概念の重複を効率的に扱う道具があります。 +Rustにおいて、そのような道具の一つが*ジェネリクス*です。 +ジェネリクスは、具体型や他のプロパティの抽象的な代役です。コンパイルやコード実行時に、 ジェネリクスの位置に何が入るかを知ることなく、ジェネリクスの振る舞いや他のジェネリクスとの関係を表現できるのです。 @@ -43,22 +44,24 @@ generic types in struct and enum definitions. それから、トレイトを使用して、ジェネリックな方法で振る舞いを定義する方法を学びます。 -ジェネリックな型にトレイトを組み合わせることで、ジェネリックな型を、単にあらゆる型に対してではなく、特定の振る舞いのある型のみに制限できます。 +ジェネリックな型にトレイトを組み合わせることで、ジェネリックな型を、単にあらゆる型に対してではなく、特定の振る舞いのある型のみを受け付けるように制限できます。 最後に、ライフタイムを議論します。ライフタイムとは、コンパイラに参照がお互いにどう関係しているかの情報を与える一種のジェネリクスです。 -ライフタイムのおかげでコンパイラに参照が有効であることを確認してもらうことを可能にしつつ、多くの場面で値を借用できます。 +ライフタイムを利用することで、借用された値についての十分な情報をコンパイラに渡すことができ、 +プログラマの支援がなくてもできる範囲よりもより多くの場面で、参照が有効であることを保証できます。 -ジェネリクスの記法に飛び込む前にまずは、関数を抽出することでジェネリックな型が関わらない重複を取り除く方法を見ましょう。 -そして、このテクニックを適用してジェネリックな関数を抽出するのです!重複したコードを認識して関数に抽出できるのと同じように、 -ジェネリクスを使用できる重複コードも認識し始めるでしょう。 +ジェネリクスを使用すると、複数の型を表現するプレースホルダで特定の型を置き換えることで、コードの重複を取り除くことができます。 +ジェネリクスの記法に飛び込む前にまずは、複数の値を表現するプレースホルダで特定の値を置き換えて関数を抽出することで、ジェネリックな型が関わらない重複を取り除く方法を見ましょう。 +そして、同じテクニックを適用してジェネリックな関数を抽出するのです! +関数に抽出できる重複したコードを認識する方法を見てみることで、ジェネリクスを使用できる重複コードも認識できるようになるでしょう。 -リスト10-1に示したように、リスト内の最大値を求める短いプログラムを考えてください。 +リスト10-1の、リスト内の最大値を求める短いプログラムで始めましょう。 -リスト10-1: 数字のリストから最大値を求めるコード +リスト10-1: 数字のリストから最大値を求める -このコードは、整数のリストを変数`number_list`に格納し、リストの最初の数字を`largest`という変数に配置しています。 -それからリストの数字全部を走査し、現在の数字が`largest`に格納された数値よりも大きければ、 -その変数の値を置き換えます。ですが、現在の数値が今まで見た最大値よりも小さければ、 +このコードは、整数のリストを変数`number_list`に格納し、リストの最初の数への参照を`largest`という変数に配置しています。 +それからリストの数全部を走査し、現在の数が`largest`に格納された数値よりも大きければ、 +その変数に代入されている参照を置き換えます。ですが、現在の数値が今まで見た最大値以下であれば、 変数は変わらず、コードはリストの次の数値に移っていきます。リストの数値全てを吟味した後、 -`largest`は最大値を保持しているはずで、今回は100になります。 +`largest`は最大値を参照しているはずで、今回は100になります。 -2つの異なる数値のリストから最大値を発見するには、リスト10-1のコードを複製し、 -プログラムの異なる2箇所で同じロジックを使用できます。リスト10-2のようにですね。 +次は2つの異なる数値のリストから最大値を発見するタスクが課されました。 +これを行うために、リスト10-1のコードを複製し、プログラムの異なる2箇所で同じロジックを使用するという手があります。リスト10-2のようにですね。 -このコードは動くものの、コードを複製することは退屈ですし、間違いも起きやすいです。また、 -コードを変更したい時に複数箇所、更新しなければなりません。 +このコードは動くものの、コードを複製することは退屈ですし、間違いも起きやすいです。 +また、コードを変更したい時には、複数箇所更新することを覚えておかなくてはなりません。 -この重複を排除するには、引数で与えられた整数のどんなリストに対しても処理が行える関数を定義して抽象化できます。 +この重複を排除するには、引数で与えられた整数のどんなリストに対しても処理が行える関数を定義して抽象化しましょう。 この解決策によりコードがより明確になり、リストの最大値を探すという概念を抽象的に表現させてくれます。 -リスト10-3では、最大値を探すコードを`largest`という関数に抽出しました。リスト10-1のコードは、 -たった1つの特定のリストからだけ最大値を探せますが、それとは異なり、このプログラムは2つの異なるリストから最大値を探せます。 +リスト10-3では、最大値を探すコードを`largest`という関数に抽出しています。 +そして、リスト10-2の2つのリストから最大値を探すために、この関数を呼んでいます。 +将来持つことになるかもしれない他のどんな`i32`値のリストに対しても、この関数を使用することができます。 `largest`関数には`list`と呼ばれる引数があり、これは、関数に渡す可能性のある、あらゆる`i32`値の具体的なスライスを示します。 結果的に、関数呼び出しの際、コードは渡した特定の値に対して走るのです。 @@ -272,7 +219,7 @@ Listing 10-3: @@ -281,13 +228,12 @@ inputs and return values of that code in the function signature. 3. 重複したコードの2つの実体を代わりに関数を呼び出すように更新する。 -次は、この同じ手順をジェネリクスでも踏んで異なる方法でコードの重複を減らします。 +次は、この同じ手順をジェネリクスでも踏んでコードの重複を減らします。 関数本体が特定の値ではなく抽象的な`list`に対して処理できたのと同様に、 ジェネリクスは抽象的な型に対して処理するコードを可能にしてくれます。 diff --git a/src/ch10-01-syntax.md b/src/ch10-01-syntax.md index f4f23eeae..b42d96f63 100644 --- a/src/ch10-01-syntax.md +++ b/src/ch10-01-syntax.md @@ -5,7 +5,7 @@ ## ジェネリックなデータ型 `largest`関数を続けます。リスト10-4はどちらもスライスから最大値を探す2つの関数を示しています。 +ここから、これらをジェネリクスを使用する単一の関数にまとめます。 -これから定義する新しい関数の型を引数にするには、ちょうど関数の値引数のように型引数に名前をつける必要があります。 +新しい単一の関数の型を引数にするには、ちょうど関数の値引数のように型引数に名前をつける必要があります。 型引数の名前にはどんな識別子も使用できますが、`T`を使用します。というのも、慣習では、 -Rustの引数名は短く(しばしばたった1文字になります)、Rustの型の命名規則がキャメルケースだからです。 +Rustの型引数名は短く(しばしばたった1文字になります)、Rustの型の命名規則がアッパーキャメルケースだからです。 "type"の省略形なので、`T`が多くのRustプログラマの既定の選択なのです。 この定義は以下のように解読します: 関数`largest`は、なんらかの型`T`に関してジェネリックであると。 この関数には`list`という引数が1つあり、これは型`T`の値のスライスです。 -`largest`関数は同じ`T`型の値を返します。 +`largest`関数は同じ`T`型の値への参照を返します。 -リスト10-5: ジェネリックな型引数を使用するものの、まだコンパイルできない`largest`関数の定義 +リスト10-5: ジェネリックな型引数を使用する`largest`関数; まだコンパイルできません src/main.rs:5:12 - | -5 | if item > largest { - | ^^^^^^^^^^^^^^ - | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `T` - (注釈: `std::cmp::PartialOrd`の実装が`T`に対して存在しない可能性があります) +```console +{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt}} ``` -注釈が`std::cmp::PartialOrd`に触れています。これは、*トレイト*です。トレイトについては、次の節で語ります。 -とりあえず、このエラーは、`largest`の本体は、`T`がなりうる全ての可能性のある型に対して動作しないと述べています。 +ヘルプメッセージが`std::cmp::PartialOrd`に触れています。これは、*トレイト*です。トレイトについては、次の節で語ります。 +今のところは、このエラーは、`largest`の本体は、`T`がなりうる可能性のある全ての型に対して動作するとは限らないと主張している、と理解してください。 本体で型`T`の値を比較したいので、値が順序付け可能な型のみしか使用できないのです。比較を可能にするために、 標準ライブラリには型に実装できる`std::cmp::PartialOrd`トレイトがあります(このトレイトについて詳しくは付録Cを参照されたし)。 -ジェネリックな型が特定のトレイトを持つと指定する方法は「トレイト境界」節で習うでしょうが、 -先にジェネリックな型引数を使用する他の方法を探究しましょう。 +ヘルプメッセージの提案に従うことで、`T`として有効な型を`PartialOrd`を実装するもののみに制限することができ、 +そうすると、標準ライブラリは`i32`と`char`の両方に`PartialOrd`を実装しているので、この例はコンパイルできるようになるでしょう。 構造体を定義して`<>`記法で1つ以上のフィールドにジェネリックな型引数を使用することもできます。 -リスト10-6は、`Point`構造体を定義してあらゆる型の`x`と`y`座標を保持する方法を示しています。 +リスト10-6は、`Point`構造体を定義してあらゆる型の`x`と`y`座標を保持しています。 -構造体定義でジェネリクスを使用する記法は、関数定義のものと似ています。まず、山カッコ内に型引数の名前を構造体名の直後に宣言します。 -そうすると、本来具体的なデータ型を記述する構造体定義の箇所に、ジェネリックな型を使用できます。 +構造体定義でジェネリクスを使用する記法は、関数定義のものと似ています。 +まず、山カッコ内に型引数の名前を構造体名の直後に宣言します。 +そして、本来具体的なデータ型を記述する構造体定義の箇所に、ジェネリックな型を使用します。 @@ -329,23 +252,15 @@ same type as `x`, we’ll get a type mismatch error like this: この例で、`x`に整数値5を代入すると、この`Point`のインスタンスに対するジェネリックな型`T`は整数になるとコンパイラに知らせます。 それから`y`に4.0を指定する時に、このフィールドは`x`と同じ型と定義したはずなので、このように型不一致エラーが出ます: -```text -error[E0308]: mismatched types - --> src/main.rs:7:38 - | -7 | let wont_work = Point { x: 5, y: 4.0 }; - | ^^^ expected integral variable, found -floating-point variable - | - = note: expected type `{integer}` - found type `{float}` +```console +{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/output.txt}} ``` `x`と`y`が両方ジェネリックだけれども、異なる型になり得る`Point`構造体を定義するには、 @@ -359,16 +274,7 @@ Listing 10-8, we can change the definition of `Point` to be generic over types ファイル名: src/main.rs ```rust -struct Point { - x: T, - y: U, -} - -fn main() { - let both_integer = Point { x: 5, y: 10 }; - let both_float = Point { x: 1.0, y: 4.0 }; - let integer_and_float = Point { x: 5, y: 4.0 }; -} +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/src/main.rs}} ``` これで、示された`Point`インスタンスは全部使用可能です!所望の数だけ定義でジェネリックな型引数を使用できますが、 -数個以上使用すると、コードが読みづらくなります。コードで多くのジェネリックな型が必要な時は、 +数個以上使用すると、コードが読みづらくなります。コードで多くのジェネリックな型が必要になることに気づいた時は、 コードの小分けが必要なサインかもしれません。 -この定義はもう、あなたにとってより道理が通っているはずです。ご覧の通り、`Option`は、 +この定義はもう、あなたにとってより道理が通っているはずです。ご覧の通り、`Option` enumは、 型`T`に関してジェネリックで2つの列挙子のあるenumです: その列挙子は、型`T`の値を保持する`Some`と、 値を何も保持しない`None`です。`Option` enumを使用することで、オプショナルな値があるという抽象的な概念を表現でき、 `Option`はジェネリックなので、オプショナルな値の型に関わらず、この抽象を使用できます。 @@ -487,22 +394,7 @@ struct we defined in Listing 10-6 with a method named `x` implemented on it. ファイル名: src/main.rs ```rust -struct Point { - x: T, - y: T, -} - -impl Point { - fn x(&self) -> &T { - &self.x - } -} - -fn main() { - let p = Point { x: 5, y: 10 }; - - println!("p.x = {}", p.x()); -} +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/src/main.rs}} ``` `impl`の直後に`T`を宣言しなければならないことに注意してください。こうすることで、型`Point`にメソッドを実装していることを指定するために、`T`を使用することができます。 `impl`の後に`T`をジェネリックな型として宣言することで、コンパイラは、`Point`の山カッコ内の型が、 具体的な型ではなくジェネリックな型であることを認識できるのです。 +このジェネリック引数には、構造体定義内で宣言したジェネリック引数とは異なる名前を選択することもできますが、 +同じ名前を使用するのが慣用的です。 +ジェネリック型を宣言する`impl`内に書かれたメソッドは、そのジェネリック型を置き換えることになる具体型が何であっても、その型のインスタンスの任意の値に対して定義されます。 +型にメソッドを定義するときに、ジェネリック型に制約を指定することもできます。 例えば、ジェネリックな型を持つ`Point`インスタンスではなく、`Point`だけにメソッドを実装することもできるでしょう。 リスト10-10では、具体的な型`f32`を使用しています。つまり、`impl`の後に型を宣言しません。 + + +ファイル名: src/main.rs + ```rust -# struct Point { -# x: T, -# y: T, -# } -# -impl Point { - fn distance_from_origin(&self) -> f32 { - (self.x.powi(2) + self.y.powi(2)).sqrt() - } -} +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/src/main.rs:here}} ``` -このコードは、`Point`には`distance_from_origin`というメソッドが存在するが、 +このコードは、`Point`には`distance_from_origin`メソッドが存在するが、 `T`が`f32`ではない`Point`の他のインスタンスにはこのメソッドが定義されないことを意味します。 このメソッドは、この点が座標(0.0, 0.0)の点からどれだけ離れているかを測定し、 浮動小数点数にのみ利用可能な数学的処理を使用します。 構造体定義のジェネリックな型引数は、必ずしもその構造体のメソッドシグニチャで使用するものと同じにはなりません。 -例を挙げれば、リスト10-11は、リスト10-8の`Point`にメソッド`mixup`を定義しています。 -このメソッドは、他の`Point`を引数として取り、この引数は`mixup`を呼び出している`self`の`Point`とは異なる型の可能性があります。 -このメソッドは、(型`T`の)`self`の`Point`の`x`値と渡した(型`W`の)`Point`の`y`値から新しい`Point`インスタンスを生成します。 +リスト10-11では、例をより見通しよくするために、`Point`構造体に対してはジェネリック型`X1`と`Y1`を使用し、 +`mixup`メソッドのシグネチャに対しては`X2`と`Y2`を使用しています。 +このメソッドは、(型`X1`の)`self`の`Point`の`x`値と渡した(型`Y2`の)`Point`の`y`値から新しい`Point`インスタンスを生成します。 リスト10-11: 構造体定義とは異なるジェネリックな型を使用するメソッド @@ -645,14 +522,15 @@ call will print `p3.x = 5, p3.y = c`. この例の目的は、一部のジェネリックな引数は`impl`で宣言され、他の一部はメソッド定義で宣言される場面をデモすることです。 -ここで、ジェネリックな引数`T`と`U`は`impl`の後に宣言されています。構造体定義にはまるからです。 -ジェネリックな引数`V`と`W`は`fn mixup`の後に宣言されています。何故なら、このメソッドにしか関係ないからです。 +ここで、ジェネリックな引数`X1`と`Y1`は`impl`の後に宣言されています。構造体定義にはまるからです。 +ジェネリックな引数`X2`と`Y2`は`fn mixup`の後に宣言されています。何故なら、このメソッドにしか関係ないからです。 ジェネリックな型引数を使用すると、実行時にコストが発生するのかな、と思うかもしれません。 -嬉しいことにRustでは、ジェネリクスを、具体的な型があるコードよりもジェネリックな型を使用したコードを実行するのが遅くならないように実装しています。 +嬉しいことに、ジェネリックな型を使用したからといって、具体的な型を使って同じことを行う場合よりもプログラムの実行が遅くなることはありません。 コンパイラはこれを、ジェネリクスを使用しているコードの単相化をコンパイル時に行うことで達成しています。 *単相化*(monomorphization)は、コンパイル時に使用されている具体的な型を入れることで、 ジェネリックなコードを特定のコードに変換する過程のことです。 - - - この過程において、コンパイラは、リスト10-5でジェネリックな関数を生成するために使用した手順と真逆のことをしています: コンパイラは、ジェネリックなコードが呼び出されている箇所全部を見て、 ジェネリックなコードが呼び出されている具体的な型のコードを生成するのです。 -標準ライブラリの`Option` enumを使用する例でこれが動作する方法を見ましょう: +標準ライブラリのジェネリックな`Option` enumを使用して、これがどう機能するのか見てみましょう: ```rust let integer = Some(5); @@ -708,23 +581,23 @@ let float = Some(5.0); When Rust compiles this code, it performs monomorphization. During that process, the compiler reads the values that have been used in `Option` instances and identifies two kinds of `Option`: one is `i32` and the other -is `f64`. As such, it expands the generic definition of `Option` into -`Option_i32` and `Option_f64`, thereby replacing the generic definition with -the specific ones. +is `f64`. As such, it expands the generic definition of `Option` into two +definitions specialized to `i32` and `f64`, thereby replacing the generic +definition with the specific ones. --> コンパイラがこのコードをコンパイルすると、単相化を行います。その過程で、コンパイラは`Option`のインスタンスに使用された値を読み取り、 2種類の`Option`を識別します: 一方は`i32`で、もう片方は`f64`です。そのように、 -コンパイラは、`Option`のジェネリックな定義を`Option_i32`と`Option_f64`に展開し、 +コンパイラは、`Option`のジェネリックな定義を`i32`と`f64`に特化した2つの定義に展開し、 それにより、ジェネリックな定義を特定の定義と置き換えます。 -単相化されたバージョンのコードは、以下のようになります。ジェネリックな`Option`が、 -コンパイラが生成した特定の定義に置き換えられています: +単相化されたバージョンのコードは、以下のようなものになります +(コンパイラは、ここで説明のために使用しているものとは異なる名前を使用します): +ジェネリックな`Option`は、コンパイラによって生成される特化された定義で置き換えられます。 Rustでは、ジェネリックなコードを各インスタンスで型を指定したコードにコンパイルするので、 ジェネリクスを使用することに対して実行時コストを払うことはありません。コードを実行すると、 それぞれの定義を手作業で複製した時のように振る舞います。単相化の過程により、 diff --git a/src/ch10-02-traits.md b/src/ch10-02-traits.md index 4fb28ae36..53f7cc045 100644 --- a/src/ch10-02-traits.md +++ b/src/ch10-02-traits.md @@ -5,15 +5,15 @@ ## トレイト: 共通の振る舞いを定義する -*トレイト*は、Rustコンパイラに、特定の型に存在し、他の型と共有できる機能について知らせます。 -トレイトを使用すると、共通の振る舞いを抽象的に定義できます。トレイト境界を使用すると、 -あるジェネリックが、特定の振る舞いをもつあらゆる型になり得ることを指定できます。 +*トレイト*は、特定の型に存在し、他の型と共有できる機能を定義します。 +トレイトを使用すると、共通の振る舞いを抽象的に定義できます。*トレイト境界*を使用すると、 +あるジェネリック型が、特定の振る舞いをもつあらゆる型になり得ることを指定できます。 -`NewsArticle` または `Tweet` インスタンスに保存されているデータのサマリーを表示できるメディア アグリゲータ ライブラリを作成します。 -これをするには、各型のサマリーが必要で、インスタンスで `summarize` メソッドを呼び出してサマリーを要求する必要があります。 -リスト10-12は、この振る舞いを表現する`Summary`トレイトの定義を表示しています。 +`NewsArticle` または `Tweet` インスタンスに保存されているデータのサマリーを表示できる`aggregator`という名前のメディア アグリゲータ ライブラリ クレートを作成します。 +これをするには、各型のサマリーが必要で、インスタンスで `summarize` メソッドを呼び出してサマリーを要求することになるでしょう。 +リスト10-12は、この振る舞いを表現する公開の`Summary`トレイトの定義を表示しています。 -ここでは、`trait`キーワード、それからトレイト名を使用してトレイトを定義していて、その名前は今回の場合、 -`Summary`です。波括弧の中にこのトレイトを実装する型の振る舞いを記述するメソッドシグニチャを定義し、 +ここでは、`trait`キーワード、それからトレイト名を使用してトレイトを宣言していて、その名前は今回の場合、 +`Summary`です。 +また、いくつかの例で見ていきますが、このクレートに依存するクレートがこのトレイトを利用できるように、トレイトを`pub`として宣言しています。 +波括弧の中にこのトレイトを実装する型の振る舞いを記述するメソッドシグニチャを定義し、 今回の場合は、`fn summarize(&self) -> String`です。 -今や `Summary` トレイトを使用して目的の動作を定義できたので、メディア アグリゲータでこれを型に実装できます。 +これで `Summary` トレイトのメソッドのシグネチャを希望通りに定義できたので、メディア アグリゲータ内の型に対してこれを実装できます。 リスト10-13は、 `Summary` トレイトを `NewsArticle` 構造体上に実装したもので、ヘッドライン、著者、そして地域情報を使って`summarize` の戻り値を作っています。 `Tweet` 構造体に関しては、ツイートの内容が既に280文字に制限されていると仮定して、ユーザー名の後にツイートのテキスト全体が続くものとして `summarize` を定義します。 @@ -136,7 +140,7 @@ already limited to 280 characters. ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/src/lib.rs:here}} ``` @@ -149,13 +153,12 @@ already limited to 280 characters. 型にトレイトを実装することは、普通のメソッドを実装することに似ています。違いは、`impl`の後に、 @@ -164,15 +167,20 @@ particular type. 波括弧を使用し、メソッド本体に特定の型のトレイトのメソッドに欲しい特定の振る舞いを入れます。 -トレイトを実装後、普通のメソッド同様に`NewsArticle`や`Tweet`のインスタンスに対してこのメソッドを呼び出せます。 -こんな感じで: +これでライブラリは`NewsArticle`と`Tweet`に対して`Summary`トレイトを実装できたので、クレートの利用者は普通のメソッド同様に`NewsArticle`や`Tweet`のインスタンスに対してこのトレイトメソッドを呼び出せます。 +唯一の違いは、ユーザは型だけではなくトレイトもスコープ内に持ち込まなくてはならないということです。 +以下は、バイナリクレートが私たちの`aggregator`ライブラリクレートをどうやって使用できるかの例です: ```rust,ignore -{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs:here}} +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/src/main.rs}} ``` -トレイト実装で注意すべき制限の1つは、トレイトか対象の型が自分のクレートに固有(local)である時のみ、 +`aggregator`クレートに依存する他のクレートも、自身の型に対して`Summary`を実装するために、`Summary`トレイトをスコープに持ち込むことができます。 +注意すべき制限の1つは、トレイトか、対象の型のうち、少なくとも一方が自分のクレートに固有(local)である時のみ、 型に対してトレイトを実装できるということです。例えば、`Display`のような標準ライブラリのトレイトを`aggregator`クレートの機能の一部として、 `Tweet`のような独自の型に実装できます。型`Tweet`が`aggregator`クレートに固有だからです。 また、`Summary`を`aggregator`クレートで`Vec`に対して実装することもできます。 @@ -222,19 +233,19 @@ trait `Summary` is local to our `aggregator` crate. しかし、外部のトレイトを外部の型に対して実装することはできません。例として、 `aggregator`クレート内で`Vec`に対して`Display`トレイトを実装することはできません。 -`Display`と`Vec`は標準ライブラリで定義され、`aggregator`クレートに固有ではないからです。 -この制限は、*コヒーレンス*(coherence)、特に*孤児のルール*(orphan rule)と呼ばれるプログラムの特性の一部で、 +`Display`と`Vec`はどちらも標準ライブラリで定義され、`aggregator`クレートに固有ではないからです。 +この制限は、*コヒーレンス*(coherence)、特に*孤児のルール*(orphan rule)と呼ばれる特性の一部で、 親の型が存在しないためにそう命名されました。この規則により、他の人のコードが自分のコードを壊したり、 その逆が起きないことを保証してくれます。この規則がなければ、2つのクレートが同じ型に対して同じトレイトを実装できてしまい、 コンパイラはどちらの実装を使うべきかわからなくなってしまうでしょう。 @@ -256,13 +267,13 @@ each method’s default behavior. そうすれば、特定の型にトレイトを実装する際、各メソッドのデフォルト実装を保持するかオーバーライドするか選べるわけです。 -リスト10-14は、リスト10-12のように、メソッドシグニチャだけを定義するのではなく、 -`Summary`トレイトの`summarize`メソッドにデフォルトの文字列を指定する方法を示しています。 +リスト10-14では、リスト10-12のように、メソッドシグニチャだけを定義するのではなく、 +`Summary`トレイトの`summarize`メソッドにデフォルトの文字列を指定しています。 -リスト10-14: `summarize`メソッドのデフォルト実装がある`Summary`トレイトの定義 +リスト10-14: `summarize`メソッドのデフォルト実装がある`Summary`トレイトを定義する -独自の実装を定義するのではなく、デフォルト実装を利用して`NewsArticle`のインスタンスをまとめるには、 +デフォルト実装を利用して`NewsArticle`のインスタンスをまとめるには、 `impl Summary for NewsArticle {}`と空の`impl`ブロックを指定します。 -`summarize`にデフォルト実装を用意しても、リスト10-13の`Tweet`の`Summary`実装を変える必要はありません。 +デフォルト実装を用意しても、リスト10-13の`Tweet`の`Summary`実装を変える必要はありません。 理由は、デフォルト実装をオーバーライドする記法はデフォルト実装のないトレイトメソッドを実装する記法と同じだからです。 トレイトを定義し実装する方法はわかったので、トレイトを使っていろんな種類の型を受け付ける関数を定義する方法を学んでいきましょう。 - - -たとえば、Listing 10-13では、`NewsArticle`と`Tweet`型に`Summary`トレイトを実装しました。 -ここで、引数の`item`の`summarize`メソッドを呼ぶ関数`notify`を定義することができます。ただし、引数`item`は`Summary`トレイトを実装しているような何らかの型であるとします。 -このようなことをするためには、`impl Trait`構文を使うことができます。 +リスト10-13で`NewsArticle`と`Tweet`に対して実装した`Summary`トレイトを使用して、`notify`関数を定義しましょう。 +この関数は、`Summary`トレイトを実装する何らかの型を持つ引数`item`を持ち、それに対して`summarize`メソッドを呼び出します。 +これを行うためには、このように`impl Trait`構文を使います: ```rust,ignore {{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/src/lib.rs:here}} @@ -424,17 +429,21 @@ because those types don’t implement `Summary`. この関数を呼び出すときに、`String`や`i32`のような他の型を渡すようなコードはコンパイルできません。 なぜなら、これらの型は`Summary`を実装していないからです。 + + + #### トレイト境界構文 -`impl Trait`構文は単純なケースを解決しますが、実はより長い*トレイト境界 (trait bound)* と呼ばれる姿の糖衣構文 (syntax sugar) なのです。 +`impl Trait`構文は単純なケースを解決しますが、実はより長い*トレイト境界 (trait bound)* として知られる姿の糖衣構文 (syntax sugar) なのです。 それは以下のようなものです: ```rust,ignore @@ -454,27 +463,27 @@ parameter after a colon and inside angle brackets. -簡単なケースに対し、`impl Trait`構文は便利で、コードを簡潔にしてくれます。 -そうでないケースの場合、トレイト境界構文を使えば複雑な状態を表現できます。 +簡単なケースでは`impl Trait`構文は便利で、コードを簡潔にしてくれます。 +一方でそうでないケースでは、完全なトレイト境界構文を使えばより複雑な制約を表現できます。 たとえば、`Summary`を実装する2つのパラメータを持つような関数を考えることができます。 -`impl Trait`構文を使うとこのようになるでしょう: +`impl Trait`構文を使ってそうするのはこのようになるでしょう: ```rust,ignore pub fn notify(item1: &impl Summary, item2: &impl Summary) { ``` -この関数が受け取る`item1`と`item2`の型が(どちらも`Summary`を実装する限り)異なっても良いとするならば、`impl Trait`は適切でしょう。 -両方の引数が同じ型であることを強制することは、以下のようにトレイト境界を使ってのみ表現可能です: +この関数が受け取る`item1`と`item2`の型が(どちらも`Summary`を実装する限り)異なっても良い場合、`impl Trait`の使用は適切です。 +しかし、両方の引数が同じ型であることを強制したい場合は、次のようにトレイト境界を使用しなくてはなりません: ```rust,ignore pub fn notify(item1: &T, item2: &T) { @@ -495,12 +504,12 @@ passed as an argument for `item1` and `item2` must be the same. 複数のトレイト境界も指定できます。 -たとえば、`notify`に`summarize`メソッドに加えて`item`の画面出力形式(ディスプレイフォーマット)を使わせたいとします。 +たとえば、`notify`に、`item`に対する`summarize`に加えて画面出力形式(ディスプレイフォーマット)も使わせたいとします。 その場合は、`notify`の定義に`item`は`Display`と`Summary`の両方を実装していなくてはならないと指定することになります。 これは、以下のように`+`構文で行うことができます: @@ -552,10 +561,7 @@ we can use a `where` clause, like this: 代わりに、`where`句を使い、このように書くことができます: ```rust,ignore -fn some_function(t: &T, u: &U) -> i32 - where T: Display + Clone, - U: Clone + Debug -{ +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-where-clause/src/lib.rs:here}} ``` 戻り値の型として`impl Summary`を使うことにより、具体的な型が何かを言うことなく、`returns_summarizable`関数は`Summary`トレイトを実装している何らかの型を返すのだ、と指定することができます。 -今回`returns_summarizable`は`Tweet`を返しますが、この関数を呼び出すコードはそのことを知りません。 +今回`returns_summarizable`は`Tweet`を返しますが、この関数を呼び出すコードはそのことを知る必要はありません。 実装しているトレイトだけで戻り値型を指定できることは、13章で学ぶ、クロージャとイテレータを扱うときに特に便利です。 クロージャとイテレータの作り出す型は、コンパイラだけが知っているものであったり、指定するには長すぎるものであったりします。 @@ -619,129 +625,11 @@ Returning either a `NewsArticle` or a `Tweet` isn’t allowed due to restriction around how the `impl Trait` syntax is implemented in the compiler. We’ll cover how to write a function with this behavior in the [“Using Trait Objects That Allow for Values of Different -Types”][using-trait-objects-that-allow-for-values-of-different-types] section of Chapter 17. +Types”][using-trait-objects-that-allow-for-values-of-different-types] +section of Chapter 17. --> `NewsArticle`か`Tweet`を返すというのは、コンパイラの`impl Trait`構文の実装まわりの制約により許されていません。 -このような振る舞いをする関数を書く方法は、17章の[トレイトオブジェクトで異なる型の値を許容する][using-trait-objects-that-allow-for-values-of-different-types]節で学びます。 - - -### トレイト境界で`largest`関数を修正する - - -ジェネリックな型引数の境界で使用したい振る舞いを指定する方法がわかったので、リスト10-5に戻って、 -ジェネリックな型引数を使用する`largest`関数の定義を修正しましょう!最後にそのコードを実行しようとした時、 -こんなエラーが出ていました: - -```text -{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt}} -``` - - -`largest`の本体で、大なり演算子(`>`)を使用して型`T`の2つの値を比較しようとしていました。この演算子は、 -標準ライブラリトレイトの`std::cmp::PartialOrd`でデフォルトメソッドとして定義されているので、 -`largest`関数が、比較できるあらゆる型のスライスに対して動くようにするためには、`T`のトレイト境界に`PartialOrd`を指定する必要があります。 -`PartialOrd`はpreludeに含まれているので、これをスコープに導入する必要はありません。 -`largest`のシグニチャを以下のように変えてください: - -```rust,ignore -{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/src/main.rs:here}} -``` - - -今回のコンパイルでは、別のエラーが出てきます: - -```console -{{#include ../listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/output.txt}} -``` - - -このエラーの鍵となる行は、`cannot move out of type [T], a non-copy slice`です。 -ジェネリックでないバージョンの`largest`関数では、最大の`i32`か`char`を探そうとするだけでした。 -第4章の[スタックのみのデータ: コピー][stack-only-data-copy]節で議論したように、`i32`や`char`のようなサイズが既知の型は -スタックに格納できるので、`Copy`トレイトを実装しています。しかし、`largest`関数をジェネリックにすると、 -`list`引数が`Copy`トレイトを実装しない型を含む可能性も出てきたのです。結果として、 -`list[0]`から値を`largest`にムーブできず、このエラーに陥ったのです。 - - -このコードを`Copy`トレイトを実装する型だけを使って呼び出すようにしたいなら、`T`のトレイト境界に`Copy`を追加すればよいです! -リスト10-15は、関数に渡したスライスの値の型が、`i32`や`char`などのように`PartialOrd`*と*`Copy`を実装する限りコンパイルできる、ジェネリックな`largest`関数の完全なコードを示しています。 - - -ファイル名: src/main.rs - -```rust -{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/main.rs}} -``` - - -リスト10-15: `PartialOrd`と`Copy`トレイトを実装するあらゆるジェネリックな型に対して動く、 -`largest`関数の実際の定義 - - -もし`largest`関数を`Copy`を実装する型だけに制限したくなかったら、`T`が`Copy`ではなく`Clone`というトレイト境界を持つと指定することもできます。そうしたら、 -`largest`関数に所有権が欲しい時にスライスの各値をクローンできます。`clone`関数を使用するということは、 -`String`のようなヒープデータを持つ型の場合により多くのヒープ確保が発生する可能性があることを意味します。 -そして、大量のデータを取り扱っていたら、ヒープ確保には時間がかかることもあります。 - - -`largest`の別の実装方法は、関数がスライスの`T`値への参照を返すようにすることです。 -戻り値の型を`T`ではなく`&T`に変え、それにより関数の本体を参照を返すように変更したら、 -`Clone`や`Copy`トレイト境界は必要なくなり、ヒープ確保も避けられるでしょう。 -これらの代替策をご自身で実装してみましょう! +このような振る舞いをする関数を書く方法は、17章の[「トレイトオブジェクトで異なる型の値を許容する」][using-trait-objects-that-allow-for-values-of-different-types]節で学びます。 ジェネリックな型引数を持つ`impl`ブロックにトレイト境界を与えることで、 特定のトレイトを実装する型に対するメソッド実装を条件分けできます。例えば、 -リスト10-16の型`Pair`は、常に`new`関数を実装します。しかし、`Pair`は、 +リスト10-15の型`Pair`は、`Pair`の新しいインスタンスを返す`new`関数を常に実装します +(第5章の[「メソッドを定義する」][methods]節で学んだ、`Self`は`impl`ブロックの型に対する型エイリアスだということを思い出してください、今回は`Pair`です)。しかし次の`impl`ブロック内では、`Pair`は、 内部の型`T`が比較を可能にする`PartialOrd`トレイト*と*出力を可能にする`Display`トレイトを実装している時のみ、 `cmp_display`メソッドを実装します。 @@ -767,15 +659,15 @@ the `Display` trait that enables printing. --> ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/lib.rs}} +```rust,noplayground +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/src/lib.rs}} ``` -リスト10-16: トレイト境界によってジェネリックな型に対するメソッド実装を条件分けする +リスト10-15: トレイト境界によってジェネリックな型に対するメソッド実装を条件分けする -すでに使っている他のジェネリクスに、ライフタイムと呼ばれるものがあります。 -ライフタイムは、型が欲しい振る舞いを保持していることではなく、必要な間だけ参照が有効であることを保証します。 -ライフタイムがどうやってそれを行うかを見てみましょう。 - -[stack-only-data-copy]: -ch04-01-what-is-ownership.html#%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%E3%81%AE%E3%81%BF%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF-%E3%82%B3%E3%83%94%E3%83%BC -[using-trait-objects-that-allow-for-values-of-different-types]: -ch17-02-trait-objects.html#%E3%83%88%E3%83%AC%E3%82%A4%E3%83%88%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A7%E7%95%B0%E3%81%AA%E3%82%8B%E5%9E%8B%E3%81%AE%E5%80%A4%E3%82%92%E8%A8%B1%E5%AE%B9%E3%81%99%E3%82%8B +[using-trait-objects-that-allow-for-values-of-different-types]: ch17-02-trait-objects.html#トレイトオブジェクトで異なる型の値を許容する +[methods]: ch05-03-method-syntax.html#メソッドを定義する diff --git a/src/ch10-03-lifetime-syntax.md b/src/ch10-03-lifetime-syntax.md index cfb1fd7e9..fb4f52dba 100644 --- a/src/ch10-03-lifetime-syntax.md +++ b/src/ch10-03-lifetime-syntax.md @@ -4,36 +4,42 @@ ## ライフタイムで参照を検証する + +ライフタイムは、すでに使ってきましたが、もう一つの種類のジェネリクスです。 +ライフタイムは、型が欲しい振る舞いを持つことを保証するのではなく、必要な間だけ参照が有効であることを保証します。 + 第4章の[「参照と借用」][references-and-borrowing]節で議論しなかった詳細の一つに、Rustにおいて参照は全てライフタイムを保持するということがあります。 ライフタイムとは、その参照が有効になるスコープのことです。多くの場合、型が推論されるように、 -大体の場合、ライフタイムも暗黙的に推論されます。複数の型の可能性があるときには、型を注釈しなければなりません。 +大体の場合、ライフタイムも暗黙的に推論されます。複数の型の可能性があるときにのみ、型を注釈しなければなりません。 同様に、参照のライフタイムがいくつか異なる方法で関係することがある場合には注釈しなければなりません。 コンパイラは、ジェネリックライフタイム引数を使用して関係を注釈し、実行時に実際の参照が確かに有効であることを保証することを要求するのです。 -ライフタイムの概念は、他のプログラミング言語の道具とはどこか異なり、間違いなくRustで一番際立った機能になっています。 +ライフタイムの注釈は、他の多くのプログラミング言語にはない概念ですので、馴染みのない気分になるでしょう。 この章では、ライフタイムの全体を解説することはしませんが、 -ライフタイム記法が必要となる最も一般的な場合について議論しますので、ライフタイムの概念について馴染むことができるでしょう。 +ライフタイム記法に遭遇するよくある場合について議論しますので、ライフタイムの概念について馴染むことができるでしょう。 -ライフタイムの主な目的は、ダングリング参照を回避することです。ダングリング参照によりプログラムは、 +ライフタイムの主な目的は、*ダングリング参照*を回避することです。ダングリング参照によりプログラムは、 参照するつもりだったデータ以外のデータを参照してしまいます。リスト10-17のプログラムを考えてください。 これには、外側のスコープと内側のスコープが含まれています。 ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs:here}} +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/src/main.rs}} ``` -リスト10-17: 値がスコープを抜けてしまった参照を使用しようとする +リスト10-16: 値がスコープを抜けてしまった参照を使用しようとする -> 注釈: リスト10-17や10-18、10-24では、変数に初期値を与えずに宣言しているので、変数名は外側のスコープに存在します。 +> 注釈: リスト10-16や10-17、10-23では、変数に初期値を与えずに宣言しているので、変数名は外側のスコープに存在します。 > 初見では、これはRustにはnull値が存在しないということと衝突しているように見えるかもしれません。 > しかしながら、値を与える前に変数を使用しようとすれば、コンパイルエラーになり、 > 確かにRustではnull値は許可されていないことがわかります。 @@ -82,7 +88,7 @@ The outer scope declares a variable named `r` with no initial value, and the inner scope declares a variable named `x` with the initial value of 5. Inside the inner scope, we attempt to set the value of `r` as a reference to `x`. Then the inner scope ends, and we attempt to print the value in `r`. This code won’t -compile because the value `r` is referring to has gone out of scope before we +compile because what the value `r` is referring to has gone out of scope before we try to use it. Here is the error message: --> @@ -92,7 +98,7 @@ try to use it. Here is the error message: このコードはコンパイルできません。こちらがエラーメッセージです: ```console -{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/output.txt}} +{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/output.txt}} ``` Rustコンパイラには、スコープを比較して全ての借用が有効であるかを決定する*借用チェッカー*があります。 -リスト10-18は、リスト10-17と同じコードを示していますが、変数のライフタイムを表示する注釈が付いています。 +リスト10-17は、リスト10-16と同じコードを示していますが、変数のライフタイムを表示する注釈が付いています。 ```rust,ignore,does_not_compile -{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs:here}} +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/src/main.rs}} ``` -リスト10-18: それぞれ`'a`と`'b`と名付けられた`r`と`x`のライフタイムの注釈 +リスト10-17: それぞれ`'a`と`'b`と名付けられた`r`と`x`のライフタイムの注釈 -リスト10-19でコードを修正したので、ダングリング参照はなくなり、エラーなくコンパイルできます。 +リスト10-18でコードを修正したので、ダングリング参照はなくなり、エラーなくコンパイルできます。 ```rust -{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/src/main.rs:here}} +{{#rustdoc_include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/src/main.rs}} ``` -リスト10-19: データのライフタイムが参照より長いので、有効な参照 +リスト10-18: データのライフタイムが参照より長いので、有効な参照 2つの文字列スライスのうち、長い方を返す関数を書きましょう。この関数は、 2つの文字列スライスを取り、1つの文字列スライスを返します。`longest`関数の実装完了後、 -リスト10-20のコードは、`The longest string is abcd`と出力するはずです。 +リスト10-19のコードは、`The longest string is abcd`と出力するはずです。 -リスト10-20: `longest`関数を呼び出して2つの文字列スライスのうち長い方を探す`main`関数 +リスト10-19: `longest`関数を呼び出して2つの文字列スライスのうち長い方を探す`main`関数 -関数に取ってほしい引数が文字列スライス、つまり参照であることに注意してください。 +関数に取ってほしい引数が文字列ではなく文字列スライス、つまり参照であることに注意してください。 何故なら、`longest`関数に引数の所有権を奪ってほしくないからです。 -リスト10-20で使用している引数が、我々が必要としているものである理由についてもっと詳しい議論は、 +リスト10-19で使用している引数が、我々が必要としているものである理由についてもっと詳しい議論は、 第4章の[「引数としての文字列スライス」][string-slices-as-parameters]節をご参照ください。 -リスト10-21に示すように`longest`関数を実装しようとしたら、コンパイルできないでしょう。 +リスト10-20に示すように`longest`関数を実装しようとしたら、コンパイルできないでしょう。 -リスト10-21: 2つの文字列スライスのうち長い方を返すけれども、コンパイルできない`longest`関数の実装 +リスト10-20: 2つの文字列スライスのうち長い方を返すけれども、コンパイルできない`longest`関数の実装 この関数を定義する際、この関数に渡される具体的な値がわからないので、`if`ケースと`else`ケースのどちらが実行されるかわからないのです。 -また、リスト10-18と10-19で、返す参照が常に有効であるかを決定したときのようにスコープを見ることも、渡される参照の具体的なライフタイムがわからないのでできないのです。 +また、リスト10-17と10-18で、返す参照が常に有効であるかを決定したときのようにスコープを見ることも、渡される参照の具体的なライフタイムがわからないのでできないのです。 借用チェッカーもこれを決定することはできません。`x`と`y`のライフタイムがどう戻り値のライフタイムと関係するかわからないからです。 このエラーを修正するために、借用チェッカーが解析を実行できるように、参照間の関係を定義するジェネリックなライフタイム引数を追加しましょう。 @@ -309,29 +315,29 @@ perform its analysis. ### ライフタイム注釈記法 -ライフタイム注釈は、いかなる参照の生存期間も変えることはありません。シグニチャにジェネリックな型引数を指定された -関数が、あらゆる型を受け取ることができるのと同様に、ジェネリックなライフタイム引数を指定された関数は、 -あらゆるライフタイムの参照を受け取ることができます。ライフタイム注釈は、ライフタイムに影響することなく、 -複数の参照のライフタイムのお互いの関係を記述します。 +ライフタイム注釈は、いかなる参照の生存期間も変えることはありません。むしろ、ライフタイムに影響することなく、 +複数の参照のライフタイムのお互いの関係を記述します。シグニチャにジェネリックな型引数を指定された関数が、 +あらゆる型を受け取ることができるのと同様に、ジェネリックなライフタイム引数を指定された関数は、 +あらゆるライフタイムの参照を受け取ることができます。 ライフタイム注釈は、少し不自然な記法です: ライフタイム引数の名前はアポストロフィー(`'`)で始まらなければならず、 -通常全部小文字で、ジェネリック型のようにとても短いです。多くの人は、`'a`という名前を使います。 +通常全部小文字で、ジェネリック型のようにとても短いです。 +多くの人は、最初のライフライム注釈に対して`'a`という名前を使います。 ライフタイム引数注釈は、参照の`&`の後に配置し、注釈と参照の型を区別するために空白を1つ使用します。 -1つのライフタイム注釈それだけでは、大して意味はありません。注釈は、複数の参照のジェネリックなライフタイム引数が、 -お互いにどう関係するかをコンパイラに指示することを意図しているからです。例えば、 -ライフタイム`'a`付きの`i32`への参照となる引数`first`のある関数があるとしましょう。 -この関数にはさらに、`'a`のライフタイム付きの`i32`への別の参照となる`second`という別の引数もあります。 -ライフタイム注釈は、`first`と`second`の参照がどちらもこのジェネリックなライフタイムと同じだけ生きることを示唆します。 +1つのライフタイム注釈それだけでは、大して意味はありません。 +注釈は、複数の参照のジェネリックなライフタイム引数が、お互いにどう関係するかをコンパイラに指示することを意図しているからです。 +`longest`関数を例に、ライフタイム注釈が互いにどう関連していくのか、詳しく見ていきましょう。 + +関数シグネチャでライフタイム注釈を使用するには、ジェネリック*型*引数でやったのとまったく同じように、 +関数名と引数リストの間の山カッコの中にジェネリックな*ライフタイム*引数を宣言します。 + + -さて、`longest`関数を例にライフタイム注釈を詳しく見ていきましょう。ジェネリックな型引数同様、 -関数名と引数リストの間の山カッコの中にジェネリックなライフタイム引数を宣言します。 -このシグニチャで表現したい制約は、引数の全ての参照と戻り値が同じライフタイムを持つことです。 -リスト10-22に示すように、ライフタイムを`'a`と名付け、それを各参照に付与します。 +このシグニチャで以下の制約を表現したいです: +返される参照は、両引数が有効である限り、有効になります。 +これが引数と戻り値の間のライフタイムの関係です。 +リスト10-21に示すように、ライフタイムを`'a`と名付け、それを各参照に付与します。 -リスト10-22: シグニチャの全参照が同じライフタイム`'a`を持つと指定した`longest`関数の定義 +リスト10-21: シグニチャの全参照が同じライフタイム`'a`を持つと指定した`longest`関数の定義 -このコードはコンパイルでき、リスト10-20の`main`関数とともに使用したら、欲しい結果になるはずです。 +このコードはコンパイルでき、リスト10-19の`main`関数とともに使用したら、欲しい結果になるはずです。 + +これで関数シグニチャは、何らかのライフタイム`'a`に対して、関数は2つの引数を取り、 +どちらも少なくともライフタイム`'a`と同じだけ生きる文字列スライスであるとコンパイラに教えるようになりました。 +また、この関数シグニチャは、関数から返る文字列スライスも少なくともライフタイム`'a`と同じだけ生きると、 +コンパイラに教えています。 +実際には、`longest`関数が返す参照のライフタイムは、関数実引数によって参照される値のうち、小さい方のライフタイムと同じであるという事です。 +これらの関係は、まさに私たちがコンパイラにこのコードを解析するときに使用してほしかったものです。 + + -これで関数シグニチャは、何らかのライフタイム`'a`に対して、関数は2つの引数を取り、 -どちらも少なくともライフタイム`'a`と同じだけ生きる文字列スライスであるとコンパイラに教えるようになりました。 -また、この関数シグニチャは、関数から返る文字列スライスも少なくともライフタイム`'a`と同じだけ生きると、 -コンパイラに教えています。 -実際には、`longest`関数が返す参照のライフタイムは、渡された参照のうち、小さい方のライフタイムと同じであるという事です。 -これらの制約は、まさに私たちがコンパイラに保証してほしかったものです。 - この関数シグニチャでライフタイム引数を指定する時、渡されたり、返したりした、いかなる値のライフタイムも変更していないことを思い出してください。 むしろ、借用チェッカーは、これらの制約を守らない値全てを拒否するべきと指定しています。 `longest`関数は、`x`と`y`の正確な生存期間を知っている必要はなく、 @@ -445,18 +456,23 @@ substituted for `'a` that will satisfy this signature. 関数にライフタイムを注釈するときは、注釈は関数の本体ではなくシグニチャに付与します。 -コンパイラは注釈がなくとも関数内のコードを解析できます。しかしながら、 -関数に関数外からの参照や関数外への参照がある場合、コンパイラが引数や戻り値のライフタイムを自力で解決することはほとんど不可能になります。 -そのライフタイムは、関数が呼び出される度に異なる可能性があります。このために、手動でライフタイムを注釈する必要があるのです。 +ライフタイム注釈は、シグニチャ内の型がそうであるように、その関数の契約の一部を構成します。 +関数シグニチャにライフタイムの契約を含めることで、コンパイラが行う解析をより簡潔にすることができます。 +関数の注釈や呼ばれる状況に問題がある場合に、コンパイラのエラーはより正確にコードと制約の問題のある部分を示すことができます。 +もしRustコンパイラが、プログラムが意図するライフタイムの関係についてこれより深く推論を行うとしたら、 +コンパイラは、問題の原因から何ステップも離れたコードを指し示すことしかできなくなるかもしれません。 ライフタイム注釈が異なる具体的なライフタイムを持つ参照を渡すことで`longest`関数を制限する方法を見ましょう。 -リスト10-23はそのシンプルな例です。 +リスト10-22はそのシンプルな例です。 -リスト10-23: 異なる具体的なライフタイムを持つ`String`値への参照で`longest`関数を使用する +リスト10-22: 異なる具体的なライフタイムを持つ`String`値への参照で`longest`関数を使用する この例において、`string1`は外側のスコープの終わりまで有効で、`string2`は内側のスコープの終わりまで有効、 そして`result`は内側のスコープの終わりまで有効な何かを参照しています。このコードを実行すると、 -借用チェッカーがこのコードを良しとするのがわかるでしょう。要するに、コンパイルでき、 +借用チェッカーが良しとするのがわかるでしょう。要するに、コンパイルでき、 `The longest string is long string is long`と出力するのです。 次に、`result`の参照のライフタイムが2つの引数の小さい方のライフタイムになることを示す例を試しましょう。 `result`変数の宣言を内側のスコープの外に移すものの、`result`変数への代入は`string2`のスコープ内に残したままにします。 それから`result`を使用する`println!`を内側のスコープの外、内側のスコープが終わった後に移動します。 -リスト10-24のコードはコンパイルできません。 +リスト10-23のコードはコンパイルできません。 -リスト10-24: `string2`がスコープを抜けてから`result`を使用しようとする +リスト10-23: `string2`がスコープを抜けてから`result`を使用しようとする このコードのコンパイルを試みると、こんなエラーになります: ```console -{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt}} +{{#include ../listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/output.txt}} ``` 人間からしたら、`string1`は`string2`よりも長く、それ故に`result`が`string1`への参照を含んでいることは @@ -579,7 +595,7 @@ disallows the code in Listing 10-24 as possibly having an invalid reference. `string1`への参照は`println!`にとって有効でしょう。ですが、コンパイラはこの場合、 参照が有効であると見なせません。`longest`関数から返ってくる参照のライフタイムは、 渡した参照のうちの小さい方と同じだとコンパイラに指示しました。したがって、 -借用チェッカーは、リスト10-24のコードを無効な参照がある可能性があるとして許可しないのです。 +借用チェッカーは、リスト10-23のコードを無効な参照がある可能性があるとして許可しないのです。 -この例では、引数`x`と戻り値に対してライフタイム引数`'a`を指定しましたが、引数`y`には指定していません。 +引数`x`と戻り値に対してライフタイム引数`'a`を指定しましたが、引数`y`には指定していません。 `y`のライフタイムは`x`や戻り値のライフタイムとは何の関係もないからです。 関数から参照を返す際、戻り値型のライフタイム引数は、引数のうちどれかのライフタイム引数と一致する必要があります。 返される参照が引数のどれかを参照*していない*ならば、この関数内で生成された値を参照しているはずです。 -すると、その値は関数の末端でスコープを抜けるので、これはダングリング参照になるでしょう。 +しかしながら、その値は関数の末端でスコープを抜けるので、これはダングリング参照になるでしょう。 以下に示す、コンパイルできない`longest`関数の未完成の実装を考えてください: -ここまで、所有された型を保持する構造体だけを定義してきました。構造体に参照を保持させることもできますが、 +ここまで定義してきた構造体はすべて所有された型を保持しています。参照を保持する構造体を定義することもできますが、 その場合、構造体定義の全参照にライフタイム注釈を付け加える必要があるでしょう。 -リスト10-25には、文字列スライスを保持する`ImportantExcerpt`(重要な一節)という構造体があります。 +リスト10-24には、文字列スライスを保持する`ImportantExcerpt`(重要な一節)という構造体があります。 -リスト10-25: 参照を含む構造体なので、定義にライフタイム注釈が必要 +リスト10-24: ライフタイム注釈を必要とする、参照を含む構造体 -この構造体には文字列スライスを保持する1つのフィールド、`part`があり、これは参照です。 +この構造体には文字列スライスを保持する単一のフィールド、`part`があり、これは参照です。 ジェネリックなデータ型同様、構造体名の後、山カッコの中にジェネリックなライフタイム引数の名前を宣言するので、 構造体定義の本体でライフタイム引数を使用できます。この注釈は、`ImportantExcerpt`のインスタンスが、 `part`フィールドに保持している参照よりも長生きしないことを意味します。 @@ -763,12 +780,12 @@ the `ImportantExcerpt` goes out of scope, so the reference in the 全参照にはライフタイムがあり、参照を使用する関数や構造体にはライフタイム引数を指定する必要があることを学びました。 -しかし、リスト4-9にあった関数(リスト10-26に再度示しました)はライフタイム注釈なしでコンパイルできました。 +しかし、リスト4-9にあった関数(リスト10-25に再度示しました)はライフタイム注釈なしでコンパイルできました。 -リスト10-26: リスト4-9で定義した、引数と戻り値型が参照であるにも関わらず、ライフタイム注釈なしでコンパイルできた関数 +リスト10-25: リスト4-9で定義した、引数と戻り値型が参照であるにも関わらず、ライフタイム注釈なしでコンパイルできた関数 省略規則は、完全な推論を提供しません。コンパイラが決定的に規則を適用できるけれども、 参照が保持するライフタイムに関してそれでも曖昧性があるなら、コンパイラは、残りの参照がなるべきライフタイムを推測しません。 -この場合コンパイラは、それらを推測するのではなくエラーを与えます。 -これらは、参照がお互いにどう関係するかを指定するライフタイム注釈を追記することで解決できます。 +コンパイラはそれらを推測するのではなく、ライフタイム注釈を追記することで解決できるようなエラーを与えます。 -コンパイラは3つの規則を活用し、明示的な注釈がない時に、参照がどんなライフタイムになるかを計算します。 +コンパイラは3つの規則を活用し、明示的な注釈がない時に、参照のライフタイムを計算します。 最初の規則は入力ライフタイムに適用され、2番目と3番目の規則は出力ライフタイムに適用されます。 コンパイラが3つの規則の最後まで到達し、それでもライフタイムを割り出せない参照があったら、 コンパイラはエラーで停止します。 これらのルールは`fn`の定義にも`impl`ブロックにも適用されます。 -最初の規則は、参照である各引数は、独自のライフタイム引数を得るというものです。換言すれば、 -1引数の関数は、1つのライフタイム引数を得るということです: `fn foo<'a>(x: &'a i32)`; +最初の規則は、コンパイラは参照である各引数に、ライフタイム引数を割り当てるというものです。 +換言すれば、1引数の関数は、1つのライフタイム引数を得るということです: `fn foo<'a>(x: &'a i32)`; 2つ引数のある関数は、2つの個別のライフタイム引数を得ます: `fn foo<'a, 'b>(x: &'a i32, y: &'b i32)`; 以下同様。 @@ -897,10 +912,10 @@ lifetime is assigned to all output lifetime parameters: `fn foo<'a>(x: &'a i32) `fn foo<'a>(x: &'a i32) -> &'a i32`。 3番目の規則は、複数の入力ライフタイム引数があるけれども、メソッドなのでそのうちの一つが`&self`や`&mut self`だったら、 @@ -908,13 +923,13 @@ much nicer to read and write because fewer symbols are necessary. この3番目の規則により、必要なシンボルの数が減るので、メソッドが遥かに読み書きしやすくなります。 -コンパイラの立場になってみましょう。これらの規則を適用して、リスト10-26の`first_word`関数のシグニチャの参照のライフタイムが何か計算します。 +コンパイラの立場になってみましょう。これらの規則を適用して、リスト10-25の`first_word`関数のシグニチャの参照のライフタイムを計算します。 シグニチャは、参照に紐づけられるライフタイムがない状態から始まります: ```rust,ignore @@ -958,10 +973,10 @@ the lifetimes in this function signature. -別の例に目を向けましょう。今回は、リスト10-21で取り掛かったときにはライフタイム引数がなかった`longest`関数です: +別の例に目を向けましょう。今回は、リスト10-20で取り掛かったときにはライフタイム引数がなかった`longest`関数です: ```rust,ignore fn longest(x: &str, y: &str) -> &str { @@ -985,13 +1000,13 @@ input lifetime. The third rule doesn’t apply either, because `longest` is a function rather than a method, so none of the parameters are `self`. After working through all three rules, we still haven’t figured out what the return type’s lifetime is. This is why we got an error trying to compile the code in -Listing 10-21: the compiler worked through the lifetime elision rules but still +Listing 10-20: the compiler worked through the lifetime elision rules but still couldn’t figure out all the lifetimes of the references in the signature. --> 2つ以上入力ライフタイムがあるので、2番目の規則は適用されないとわかります。また3番目の規則も適用されません。 `longest`はメソッドではなく関数なので、どの引数も`self`ではないのです。3つの規則全部を適用した後でも、 -まだ戻り値型のライフタイムが判明していません。このために、リスト10-21でこのコードをコンパイルしようとしてエラーになったのです: +まだ戻り値型のライフタイムが判明していません。このために、リスト10-20でこのコードをコンパイルしようとしてエラーになったのです: コンパイラは、ライフタイム省略規則全てを適用したけれども、シグニチャの参照全部のライフタイムを計算できなかったのです。 `impl`ブロック内のメソッドシグニチャでは、参照は構造体のフィールドの参照のライフタイムに紐づいている可能性と、 独立している可能性があります。加えて、ライフタイム省略規則により、メソッドシグニチャでライフタイム注釈が必要なくなることがよくあります。 -リスト10-25で定義した`ImportantExcerpt`という構造体を使用した例をいくつか見てみましょう。 +リスト10-24で定義した`ImportantExcerpt`という構造体を使用した例をいくつか見てみましょう。 -議論する必要のある1種の特殊なライフタイムが、`'static`であり、これは、この参照がプログラムの全期間生存*できる*事を意味します。 +議論する必要のある1種の特殊なライフタイムが`'static`であり、これは影響を受ける参照がプログラムの全期間生存*できる*ことを示します。 文字列リテラルは全て`'static`ライフタイムになり、次のように注釈できます: ```rust @@ -1115,16 +1130,15 @@ is always available. Therefore, the lifetime of all string literals is You might see suggestions to use the `'static` lifetime in error messages. But before specifying `'static` as the lifetime for a reference, think about whether the reference you have actually lives the entire lifetime of your -program or not. You might consider whether you want it to live that long, even -if it could. Most of the time, the problem results from attempting to create a -dangling reference or a mismatch of the available lifetimes. In such cases, the -solution is fixing those problems, not specifying the `'static` lifetime. +program or not, and whether you want it to. Most of the time, an error message +suggesting the `'static` lifetime results from attempting to create a dangling +reference or a mismatch of the available lifetimes. In such cases, the solution +is fixing those problems, not specifying the `'static` lifetime. --> エラーメッセージで、`'static`ライフタイムを使用するよう勧める提言を見かける可能性があります。 -ですが、参照に対してライフタイムとして`'static`を指定する前に、今ある参照が本当にプログラムの全期間生きるかどうか考えてください。 -それが可能であったとしても、参照がそれだけの期間生きてほしいのかどうか考慮するのも良いでしょう。 -ほとんどの場合、問題は、ダングリング参照を生成しようとしているか、利用可能なライフタイムの不一致が原因です。 +ですが、参照に対してライフタイムとして`'static`を指定する前に、今ある参照が本当にプログラムの全期間生きるかどうか、そして生きてほしいのかどうか、考えてください。 +ほとんどの場合、`'static`ライフタイムを提案するエラーメッセージは、ダングリング参照を生成しようとしているか、利用可能なライフタイムの不一致が原因です。 そのような場合、解決策はその問題を修正することであり、`'static`ライフタイムを指定することではありません。 -これがリスト10-22からの2つの文字列のうち長い方を返す`longest`関数ですが、 +これがリスト10-21からの2つの文字列のうち長い方を返す`longest`関数ですが、 ジェネリックな型`T`の`ann`という追加の引数があり、これは`where`節で指定されているように、 `Display`トレイトを実装するあらゆる型で埋めることができます。 -この追加の引数は、関数が文字列スライスの長さを比較する前に出力されるので、 -`Display`トレイト境界が必要なのです。ライフタイムは一種のジェネリックなので、 -ライフタイム引数`'a`とジェネリックな型引数`T`が関数名の後、山カッコ内の同じリストに収まっています。 +この追加の引数は`{}`を使用して出力されるので、`Display`トレイト境界が必要なのです。 +ライフタイムは一種のジェネリックなので、ライフタイム引数`'a`とジェネリックな型引数`T`が関数名の後、 +山カッコ内の同じリストに収まっています。 + [references-and-borrowing]: ch04-02-references-and-borrowing.html#参照と借用 [string-slices-as-parameters]: