From eb9c6e7b0336ace6e779580922a8ec0778957757 Mon Sep 17 00:00:00 2001 From: Henri Fontana Date: Sat, 26 Aug 2023 07:33:50 -0700 Subject: [PATCH] ja: Refresh .po file after mdbook-i18n-helpers 0.2.2 (#1128) Part of #330, #282, #652 --- po/ja.po | 9109 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 5206 insertions(+), 3903 deletions(-) diff --git a/po/ja.po b/po/ja.po index 103b2ab2..6dcc8c9f 100644 --- a/po/ja.po +++ b/po/ja.po @@ -5,133 +5,133 @@ msgstr "" "PO-Revision-Date: 2023-06-06 13:18+0900\n" "Last-Translator: Kenta Aratani \n" "Language-Team: Japanese \n" +"Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: ja\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: src/SUMMARY.md:3 src/welcome.md:1 +#: src/SUMMARY.md:4 src/index.md:1 msgid "Welcome to Comprehensive Rust 🦀" msgstr "" -#: src/SUMMARY.md:4 src/running-the-course.md:1 +#: src/SUMMARY.md:5 src/running-the-course.md:1 msgid "Running the Course" msgstr "講座の運営について" -#: src/SUMMARY.md:5 src/running-the-course/course-structure.md:1 +#: src/SUMMARY.md:6 src/running-the-course/course-structure.md:1 msgid "Course Structure" msgstr "" -#: src/SUMMARY.md:6 src/running-the-course/keyboard-shortcuts.md:1 +#: src/SUMMARY.md:7 src/running-the-course/keyboard-shortcuts.md:1 msgid "Keyboard Shortcuts" msgstr "" -#: src/SUMMARY.md:7 src/running-the-course/translations.md:1 +#: src/SUMMARY.md:8 src/running-the-course/translations.md:1 msgid "Translations" msgstr "翻訳" -#: src/SUMMARY.md:8 src/cargo.md:1 +#: src/SUMMARY.md:9 src/cargo.md:1 msgid "Using Cargo" msgstr "" -#: src/SUMMARY.md:9 +#: src/SUMMARY.md:10 msgid "Rust Ecosystem" msgstr "" -#: src/SUMMARY.md:10 +#: src/SUMMARY.md:11 msgid "Code Samples" msgstr "" -#: src/SUMMARY.md:11 +#: src/SUMMARY.md:12 msgid "Running Cargo Locally" msgstr "ローカル環境での実行" -#: src/SUMMARY.md:14 +#: src/SUMMARY.md:15 msgid "Day 1: Morning" msgstr "Day 1: AM" -#: src/SUMMARY.md:18 src/SUMMARY.md:75 src/SUMMARY.md:128 src/SUMMARY.md:185 -#: src/SUMMARY.md:211 src/SUMMARY.md:259 +#: src/SUMMARY.md:19 src/SUMMARY.md:79 src/SUMMARY.md:137 src/SUMMARY.md:195 +#: src/SUMMARY.md:221 src/SUMMARY.md:271 msgid "Welcome" msgstr "Welcome" -#: src/SUMMARY.md:19 src/welcome-day-1/what-is-rust.md:1 +#: src/SUMMARY.md:20 src/welcome-day-1/what-is-rust.md:1 msgid "What is Rust?" msgstr "Rustとは?" -#: src/SUMMARY.md:20 src/hello-world.md:1 +#: src/SUMMARY.md:21 src/hello-world.md:1 msgid "Hello World!" msgstr "" -#: src/SUMMARY.md:21 src/hello-world/small-example.md:1 +#: src/SUMMARY.md:22 src/hello-world/small-example.md:1 msgid "Small Example" msgstr "プログラムの例" -#: src/SUMMARY.md:22 src/why-rust.md:1 +#: src/SUMMARY.md:23 src/why-rust.md:1 msgid "Why Rust?" msgstr "" -#: src/SUMMARY.md:23 src/why-rust/compile-time.md:1 +#: src/SUMMARY.md:24 src/why-rust/compile-time.md:1 msgid "Compile Time Guarantees" msgstr "コンパイル時の保証" -#: src/SUMMARY.md:24 src/why-rust/runtime.md:1 +#: src/SUMMARY.md:25 src/why-rust/runtime.md:1 msgid "Runtime Guarantees" msgstr "実行時の保証" -#: src/SUMMARY.md:25 src/why-rust/modern.md:1 +#: src/SUMMARY.md:26 src/why-rust/modern.md:1 msgid "Modern Features" msgstr "現代的な機能" -#: src/SUMMARY.md:26 src/basic-syntax.md:1 +#: src/SUMMARY.md:27 src/basic-syntax.md:1 msgid "Basic Syntax" msgstr "" -#: src/SUMMARY.md:27 src/basic-syntax/scalar-types.md:1 +#: src/SUMMARY.md:28 src/basic-syntax/scalar-types.md:1 msgid "Scalar Types" msgstr "" -#: src/SUMMARY.md:28 src/basic-syntax/compound-types.md:1 +#: src/SUMMARY.md:29 src/basic-syntax/compound-types.md:1 msgid "Compound Types" msgstr "" -#: src/SUMMARY.md:29 src/basic-syntax/references.md:1 +#: src/SUMMARY.md:30 src/basic-syntax/references.md:1 msgid "References" msgstr "" -#: src/SUMMARY.md:30 src/basic-syntax/references-dangling.md:1 +#: src/SUMMARY.md:31 src/basic-syntax/references-dangling.md:1 msgid "Dangling References" msgstr "" -#: src/SUMMARY.md:31 src/basic-syntax/slices.md:1 +#: src/SUMMARY.md:32 src/basic-syntax/slices.md:1 msgid "Slices" msgstr "スライス型" -#: src/SUMMARY.md:32 +#: src/SUMMARY.md:33 msgid "String vs str" msgstr "文字列(String) vs 文字列スライス(str)" -#: src/SUMMARY.md:33 src/basic-syntax/functions.md:1 +#: src/SUMMARY.md:34 src/basic-syntax/functions.md:1 msgid "Functions" msgstr "関数" -#: src/SUMMARY.md:34 src/basic-syntax/rustdoc.md:1 +#: src/SUMMARY.md:35 src/basic-syntax/rustdoc.md:1 msgid "Rustdoc" msgstr "Rustdoc" -#: src/SUMMARY.md:35 src/SUMMARY.md:82 src/basic-syntax/methods.md:1 +#: src/SUMMARY.md:36 src/SUMMARY.md:107 src/basic-syntax/methods.md:1 #: src/methods.md:1 msgid "Methods" msgstr "メソッド" -#: src/SUMMARY.md:36 +#: src/SUMMARY.md:37 msgid "Overloading" msgstr "オーバーロード" -#: src/SUMMARY.md:37 src/SUMMARY.md:66 src/SUMMARY.md:90 src/SUMMARY.md:119 -#: src/SUMMARY.md:148 src/SUMMARY.md:177 src/SUMMARY.md:204 src/SUMMARY.md:225 -#: src/SUMMARY.md:251 src/SUMMARY.md:273 src/SUMMARY.md:293 +#: src/SUMMARY.md:38 src/SUMMARY.md:71 src/SUMMARY.md:100 src/SUMMARY.md:110 +#: src/SUMMARY.md:129 src/SUMMARY.md:157 src/SUMMARY.md:187 src/SUMMARY.md:214 +#: src/SUMMARY.md:235 src/SUMMARY.md:263 src/SUMMARY.md:285 src/SUMMARY.md:306 #: src/exercises/android/morning.md:1 src/exercises/bare-metal/morning.md:1 #: src/exercises/bare-metal/afternoon.md:1 #: src/exercises/concurrency/morning.md:1 @@ -139,895 +139,914 @@ msgstr "オーバーロード" msgid "Exercises" msgstr "練習問題" -#: src/SUMMARY.md:38 src/exercises/day-1/implicit-conversions.md:1 +#: src/SUMMARY.md:39 src/exercises/day-1/implicit-conversions.md:1 msgid "Implicit Conversions" msgstr "暗黙的な型変換" -#: src/SUMMARY.md:39 +#: src/SUMMARY.md:40 msgid "Arrays and for Loops" msgstr "配列とforループ" -#: src/SUMMARY.md:41 +#: src/SUMMARY.md:42 msgid "Day 1: Afternoon" msgstr "Day 1: PM" -#: src/SUMMARY.md:43 src/basic-syntax/variables.md:1 +#: src/SUMMARY.md:44 src/SUMMARY.md:298 src/control-flow.md:1 +msgid "Control Flow" +msgstr "制御フロー" + +#: src/SUMMARY.md:45 src/control-flow/blocks.md:1 +msgid "Blocks" +msgstr "コードブロック" + +#: src/SUMMARY.md:46 +msgid "if expressions" +msgstr "if式" + +#: src/SUMMARY.md:47 +msgid "for expressions" +msgstr "for式" + +#: src/SUMMARY.md:48 +msgid "while expressions" +msgstr "while式" + +#: src/SUMMARY.md:49 +msgid "break & continue" +msgstr "break & continue" + +#: src/SUMMARY.md:50 +msgid "loop expressions" +msgstr "loop式" + +#: src/SUMMARY.md:52 src/basic-syntax/variables.md:1 msgid "Variables" msgstr "変数" -#: src/SUMMARY.md:44 src/basic-syntax/type-inference.md:1 +#: src/SUMMARY.md:53 src/basic-syntax/type-inference.md:1 msgid "Type Inference" msgstr "型推論" -#: src/SUMMARY.md:45 +#: src/SUMMARY.md:54 msgid "static & const" msgstr "static & const" -#: src/SUMMARY.md:46 src/basic-syntax/scopes-shadowing.md:1 +#: src/SUMMARY.md:55 src/basic-syntax/scopes-shadowing.md:1 msgid "Scopes and Shadowing" msgstr "スコープとシャドーイング" -#: src/SUMMARY.md:47 src/memory-management.md:1 -msgid "Memory Management" -msgstr "メモリ管理" - -#: src/SUMMARY.md:48 -msgid "Stack vs Heap" -msgstr "スタック vs ヒープ" - -#: src/SUMMARY.md:49 src/memory-management/stack.md:1 -msgid "Stack Memory" -msgstr "スタックメモリ" - -#: src/SUMMARY.md:50 src/memory-management/manual.md:1 -msgid "Manual Memory Management" -msgstr "手動でのメモリ管理" - -#: src/SUMMARY.md:51 src/memory-management/scope-based.md:1 -msgid "Scope-Based Memory Management" -msgstr "スコープに基づくメモリ管理" - -#: src/SUMMARY.md:52 -msgid "Garbage Collection" -msgstr "ガベージコレクション" - -#: src/SUMMARY.md:53 -msgid "Rust Memory Management" -msgstr "Rustのメモリ管理" - -#: src/SUMMARY.md:54 src/memory-management/comparison.md:1 -msgid "Comparison" -msgstr "比較" - -#: src/SUMMARY.md:55 src/ownership.md:1 -msgid "Ownership" -msgstr "所有権" - -#: src/SUMMARY.md:56 src/ownership/move-semantics.md:1 -msgid "Move Semantics" -msgstr "ムーブセマンティクス" - -#: src/SUMMARY.md:57 src/ownership/moved-strings-rust.md:1 -msgid "Moved Strings in Rust" -msgstr "文字列のムーブ" - -#: src/SUMMARY.md:58 src/ownership/double-free-modern-cpp.md:1 -msgid "Double Frees in Modern C++" -msgstr "現代C++の二重解放" - -#: src/SUMMARY.md:59 src/ownership/moves-function-calls.md:1 -msgid "Moves in Function Calls" -msgstr "関数とムーブ" - -#: src/SUMMARY.md:60 src/ownership/copy-clone.md:1 -msgid "Copying and Cloning" -msgstr "コピーとクローン" - -#: src/SUMMARY.md:61 src/ownership/borrowing.md:1 -msgid "Borrowing" -msgstr "借用" - -#: src/SUMMARY.md:62 src/ownership/shared-unique-borrows.md:1 -msgid "Shared and Unique Borrows" -msgstr "共有参照と固有参照" - -#: src/SUMMARY.md:63 src/ownership/lifetimes.md:1 -msgid "Lifetimes" -msgstr "ライフタイム" - -#: src/SUMMARY.md:64 src/ownership/lifetimes-function-calls.md:1 -msgid "Lifetimes in Function Calls" -msgstr "関数とライフタイム" - -#: src/SUMMARY.md:65 src/ownership/lifetimes-data-structures.md:1 -msgid "Lifetimes in Data Structures" -msgstr "データ構造とライフタイム" - -#: src/SUMMARY.md:67 src/exercises/day-1/book-library.md:1 -#: src/exercises/day-1/solutions-afternoon.md:3 -msgid "Designing a Library" -msgstr "ライブラリをデザイン" - -#: src/SUMMARY.md:68 src/exercises/day-1/iterators-and-ownership.md:1 -msgid "Iterators and Ownership" -msgstr "イテレータと所有権" - -#: src/SUMMARY.md:71 -msgid "Day 2: Morning" -msgstr "Day 2: AM" - -#: src/SUMMARY.md:76 src/structs.md:1 -msgid "Structs" -msgstr "構造体(structs)" - -#: src/SUMMARY.md:77 src/structs/tuple-structs.md:1 -msgid "Tuple Structs" -msgstr "タプル構造体" - -#: src/SUMMARY.md:78 src/structs/field-shorthand.md:1 -msgid "Field Shorthand Syntax" -msgstr "フィールドの省略" - -#: src/SUMMARY.md:79 src/enums.md:1 +#: src/SUMMARY.md:56 src/enums.md:1 msgid "Enums" msgstr "列挙型(enums)" -#: src/SUMMARY.md:80 src/enums/variant-payloads.md:1 +#: src/SUMMARY.md:57 src/enums/variant-payloads.md:1 msgid "Variant Payloads" msgstr "列挙子のペイロード" -#: src/SUMMARY.md:81 src/enums/sizes.md:1 +#: src/SUMMARY.md:58 src/enums/sizes.md:1 msgid "Enum Sizes" msgstr "列挙型のサイズ" -#: src/SUMMARY.md:83 src/methods/receiver.md:1 +#: src/SUMMARY.md:60 src/control-flow/novel.md:1 +#, fuzzy +msgid "Novel Control Flow" +msgstr "制御フロー" + +#: src/SUMMARY.md:61 +msgid "if let expressions" +msgstr "if let式" + +#: src/SUMMARY.md:62 +msgid "while let expressions" +msgstr "while let式" + +#: src/SUMMARY.md:63 +msgid "match expressions" +msgstr "match式" + +#: src/SUMMARY.md:65 src/pattern-matching.md:1 +msgid "Pattern Matching" +msgstr "パターンマッチング" + +#: src/SUMMARY.md:66 src/pattern-matching/destructuring-enums.md:1 +msgid "Destructuring Enums" +msgstr "列挙型編" + +#: src/SUMMARY.md:67 src/pattern-matching/destructuring-structs.md:1 +msgid "Destructuring Structs" +msgstr "構造体編" + +#: src/SUMMARY.md:68 src/pattern-matching/destructuring-arrays.md:1 +msgid "Destructuring Arrays" +msgstr "配列編" + +#: src/SUMMARY.md:69 src/pattern-matching/match-guards.md:1 +msgid "Match Guards" +msgstr "マッチガード" + +#: src/SUMMARY.md:72 src/exercises/day-1/luhn.md:1 +#: src/exercises/day-1/solutions-afternoon.md:3 +msgid "Luhn Algorithm" +msgstr "Luhnアルゴリズム" + +#: src/SUMMARY.md:73 +#, fuzzy +msgid "Pattern Matching (TBD)" +msgstr "パターンマッチング" + +#: src/SUMMARY.md:75 +msgid "Day 2: Morning" +msgstr "Day 2: AM" + +#: src/SUMMARY.md:81 src/memory-management.md:1 +msgid "Memory Management" +msgstr "メモリ管理" + +#: src/SUMMARY.md:82 +msgid "Stack vs Heap" +msgstr "スタック vs ヒープ" + +#: src/SUMMARY.md:83 +msgid "Stack Memory" +msgstr "スタックメモリ" + +#: src/SUMMARY.md:84 src/memory-management/manual.md:1 +msgid "Manual Memory Management" +msgstr "手動でのメモリ管理" + +#: src/SUMMARY.md:85 src/memory-management/scope-based.md:1 +msgid "Scope-Based Memory Management" +msgstr "スコープに基づくメモリ管理" + +#: src/SUMMARY.md:86 +msgid "Garbage Collection" +msgstr "ガベージコレクション" + +#: src/SUMMARY.md:87 +msgid "Rust Memory Management" +msgstr "Rustのメモリ管理" + +#: src/SUMMARY.md:88 src/memory-management/comparison.md:1 +msgid "Comparison" +msgstr "比較" + +#: src/SUMMARY.md:89 src/ownership.md:1 +msgid "Ownership" +msgstr "所有権" + +#: src/SUMMARY.md:90 src/ownership/move-semantics.md:1 +msgid "Move Semantics" +msgstr "ムーブセマンティクス" + +#: src/SUMMARY.md:91 src/ownership/moved-strings-rust.md:1 +msgid "Moved Strings in Rust" +msgstr "文字列のムーブ" + +#: src/SUMMARY.md:92 +msgid "Double Frees in Modern C++" +msgstr "現代C++の二重解放" + +#: src/SUMMARY.md:93 src/ownership/moves-function-calls.md:1 +msgid "Moves in Function Calls" +msgstr "関数とムーブ" + +#: src/SUMMARY.md:94 src/ownership/copy-clone.md:1 +msgid "Copying and Cloning" +msgstr "コピーとクローン" + +#: src/SUMMARY.md:95 src/ownership/borrowing.md:1 +msgid "Borrowing" +msgstr "借用" + +#: src/SUMMARY.md:96 src/ownership/shared-unique-borrows.md:1 +msgid "Shared and Unique Borrows" +msgstr "共有参照と固有参照" + +#: src/SUMMARY.md:97 src/ownership/lifetimes.md:1 +msgid "Lifetimes" +msgstr "ライフタイム" + +#: src/SUMMARY.md:98 src/ownership/lifetimes-function-calls.md:1 +msgid "Lifetimes in Function Calls" +msgstr "関数とライフタイム" + +#: src/SUMMARY.md:99 src/ownership/lifetimes-data-structures.md:1 +msgid "Lifetimes in Data Structures" +msgstr "データ構造とライフタイム" + +#: src/SUMMARY.md:101 src/exercises/day-2/book-library.md:1 +#, fuzzy +msgid "Storing Books" +msgstr "文字列(String)" + +#: src/SUMMARY.md:102 src/exercises/day-2/iterators-and-ownership.md:1 +msgid "Iterators and Ownership" +msgstr "イテレータと所有権" + +#: src/SUMMARY.md:104 src/structs.md:1 +msgid "Structs" +msgstr "構造体(structs)" + +#: src/SUMMARY.md:105 src/structs/tuple-structs.md:1 +msgid "Tuple Structs" +msgstr "タプル構造体" + +#: src/SUMMARY.md:106 src/structs/field-shorthand.md:1 +msgid "Field Shorthand Syntax" +msgstr "フィールドの省略" + +#: src/SUMMARY.md:108 src/methods/receiver.md:1 msgid "Method Receiver" msgstr "メソッドレシーバ" -#: src/SUMMARY.md:84 src/SUMMARY.md:159 src/SUMMARY.md:272 +#: src/SUMMARY.md:109 src/SUMMARY.md:169 src/SUMMARY.md:284 #: src/methods/example.md:1 src/concurrency/shared_state/example.md:1 msgid "Example" msgstr "例" -#: src/SUMMARY.md:85 src/pattern-matching.md:1 -msgid "Pattern Matching" -msgstr "パターンマッチング" - -#: src/SUMMARY.md:86 src/pattern-matching/destructuring-enums.md:1 -msgid "Destructuring Enums" -msgstr "列挙型編" - -#: src/SUMMARY.md:87 src/pattern-matching/destructuring-structs.md:1 -msgid "Destructuring Structs" -msgstr "構造体編" - -#: src/SUMMARY.md:88 src/pattern-matching/destructuring-arrays.md:1 -msgid "Destructuring Arrays" -msgstr "配列編" - -#: src/SUMMARY.md:89 src/pattern-matching/match-guards.md:1 -msgid "Match Guards" -msgstr "マッチガード" - -#: src/SUMMARY.md:91 src/exercises/day-2/health-statistics.md:1 +#: src/SUMMARY.md:111 src/exercises/day-2/health-statistics.md:1 msgid "Health Statistics" msgstr "健康統計" -#: src/SUMMARY.md:92 src/exercises/day-2/solutions-morning.md:3 -msgid "Points and Polygons" -msgstr "ポイントとポリゴン" - -#: src/SUMMARY.md:94 +#: src/SUMMARY.md:113 msgid "Day 2: Afternoon" msgstr "Day 2: PM" -#: src/SUMMARY.md:96 src/SUMMARY.md:286 src/control-flow.md:1 -msgid "Control Flow" -msgstr "制御フロー" - -#: src/SUMMARY.md:97 src/control-flow/blocks.md:1 -msgid "Blocks" -msgstr "コードブロック" - -#: src/SUMMARY.md:98 -msgid "if expressions" -msgstr "if式" - -#: src/SUMMARY.md:99 -msgid "if let expressions" -msgstr "if let式" - -#: src/SUMMARY.md:100 -msgid "while expressions" -msgstr "while式" - -#: src/SUMMARY.md:101 -msgid "while let expressions" -msgstr "while let式" - -#: src/SUMMARY.md:102 -msgid "for expressions" -msgstr "for式" - -#: src/SUMMARY.md:103 -msgid "loop expressions" -msgstr "loop式" - -#: src/SUMMARY.md:104 -msgid "match expressions" -msgstr "match式" - -#: src/SUMMARY.md:105 -msgid "break & continue" -msgstr "break & continue" - -#: src/SUMMARY.md:106 src/std.md:1 +#: src/SUMMARY.md:115 src/std.md:1 msgid "Standard Library" msgstr "標準ライブラリ" -#: src/SUMMARY.md:107 +#: src/SUMMARY.md:116 msgid "Option and Result" msgstr "OptionとResult" -#: src/SUMMARY.md:108 src/std/string.md:1 +#: src/SUMMARY.md:117 src/std/string.md:1 msgid "String" msgstr "文字列(String)" -#: src/SUMMARY.md:109 +#: src/SUMMARY.md:118 msgid "Vec" msgstr "ベクタ(Vec)" -#: src/SUMMARY.md:110 +#: src/SUMMARY.md:119 msgid "HashMap" msgstr "ハッシュマップ(HashMap)" -#: src/SUMMARY.md:111 +#: src/SUMMARY.md:120 msgid "Box" msgstr "ボックス(Box)" -#: src/SUMMARY.md:112 +#: src/SUMMARY.md:121 msgid "Recursive Data Types" msgstr "再帰的データ型" -#: src/SUMMARY.md:113 src/std/box-niche.md:1 +#: src/SUMMARY.md:122 src/std/box-niche.md:1 msgid "Niche Optimization" msgstr "Niche最適化" -#: src/SUMMARY.md:114 +#: src/SUMMARY.md:123 msgid "Rc" msgstr "Rc" -#: src/SUMMARY.md:115 src/modules.md:1 +#: src/SUMMARY.md:124 +msgid "Cell/RefCell" +msgstr "" + +#: src/SUMMARY.md:125 src/modules.md:1 msgid "Modules" msgstr "モジュール" -#: src/SUMMARY.md:116 src/modules/visibility.md:1 +#: src/SUMMARY.md:126 src/modules/visibility.md:1 msgid "Visibility" msgstr "可視性" -#: src/SUMMARY.md:117 src/modules/paths.md:1 +#: src/SUMMARY.md:127 src/modules/paths.md:1 msgid "Paths" msgstr "パス" -#: src/SUMMARY.md:118 src/modules/filesystem.md:1 +#: src/SUMMARY.md:128 src/modules/filesystem.md:1 msgid "Filesystem Hierarchy" msgstr "ファイルシステム階層" -#: src/SUMMARY.md:120 src/exercises/day-2/luhn.md:1 +#: src/SUMMARY.md:130 src/exercises/day-2/strings-iterators.md:1 #: src/exercises/day-2/solutions-afternoon.md:3 -msgid "Luhn Algorithm" -msgstr "Luhnアルゴリズム" - -#: src/SUMMARY.md:121 src/exercises/day-2/strings-iterators.md:1 -#: src/exercises/day-2/solutions-afternoon.md:97 msgid "Strings and Iterators" msgstr "文字列とイテレータ" -#: src/SUMMARY.md:124 +#: src/SUMMARY.md:133 msgid "Day 3: Morning" msgstr "Day 3: AM" -#: src/SUMMARY.md:129 src/generics.md:1 +#: src/SUMMARY.md:138 src/generics.md:1 msgid "Generics" msgstr "ジェネリクス(generics)" -#: src/SUMMARY.md:130 src/generics/data-types.md:1 +#: src/SUMMARY.md:139 src/generics/data-types.md:1 msgid "Generic Data Types" msgstr "ジェネリックデータ型" -#: src/SUMMARY.md:131 src/generics/methods.md:1 +#: src/SUMMARY.md:140 src/generics/methods.md:1 msgid "Generic Methods" msgstr "ジェネリックメソッド" -#: src/SUMMARY.md:132 src/generics/monomorphization.md:1 +#: src/SUMMARY.md:141 src/generics/monomorphization.md:1 msgid "Monomorphization" msgstr "単相化" -#: src/SUMMARY.md:133 src/traits.md:1 +#: src/SUMMARY.md:142 src/traits.md:1 msgid "Traits" msgstr "トレイト(trait)" -#: src/SUMMARY.md:134 src/traits/trait-objects.md:1 +#: src/SUMMARY.md:143 src/traits/trait-objects.md:1 msgid "Trait Objects" msgstr "トレイトオブジェクト" -#: src/SUMMARY.md:135 src/traits/deriving-traits.md:1 +#: src/SUMMARY.md:144 src/traits/deriving-traits.md:1 msgid "Deriving Traits" msgstr "トレイトの導出" -#: src/SUMMARY.md:136 src/traits/default-methods.md:1 +#: src/SUMMARY.md:145 src/traits/default-methods.md:1 msgid "Default Methods" msgstr "デフォルトメソッド" -#: src/SUMMARY.md:137 src/traits/trait-bounds.md:1 +#: src/SUMMARY.md:146 src/traits/trait-bounds.md:1 msgid "Trait Bounds" msgstr "トレイト境界" -#: src/SUMMARY.md:138 +#: src/SUMMARY.md:147 msgid "impl Trait" msgstr "impl Trait" -#: src/SUMMARY.md:139 src/traits/important-traits.md:1 +#: src/SUMMARY.md:148 src/traits/important-traits.md:1 msgid "Important Traits" msgstr "重要なトレイト" -#: src/SUMMARY.md:140 +#: src/SUMMARY.md:149 msgid "Iterator" msgstr "Iterator" -#: src/SUMMARY.md:141 src/traits/from-iterator.md:1 +#: src/SUMMARY.md:150 src/traits/from-iterator.md:1 msgid "FromIterator" msgstr "FromIterator" -#: src/SUMMARY.md:142 +#: src/SUMMARY.md:151 msgid "From and Into" msgstr "FromとInto" -#: src/SUMMARY.md:143 +#: src/SUMMARY.md:152 msgid "Read and Write" msgstr "ReadとWrite" -#: src/SUMMARY.md:144 +#: src/SUMMARY.md:153 msgid "Drop" msgstr "Drop" -#: src/SUMMARY.md:145 +#: src/SUMMARY.md:154 msgid "Default" msgstr "Default" -#: src/SUMMARY.md:146 +#: src/SUMMARY.md:155 msgid "Operators: Add, Mul, ..." msgstr "演算子: Add, Mul, …" -#: src/SUMMARY.md:147 +#: src/SUMMARY.md:156 msgid "Closures: Fn, FnMut, FnOnce" msgstr "クロージャ:Fn, FnMut, FnOnce" -#: src/SUMMARY.md:149 src/exercises/day-3/simple-gui.md:1 +#: src/SUMMARY.md:158 src/exercises/day-3/simple-gui.md:1 #: src/exercises/day-3/solutions-morning.md:3 msgid "A Simple GUI Library" msgstr "GUIライブラリ" -#: src/SUMMARY.md:151 +#: src/SUMMARY.md:159 src/exercises/day-3/solutions-morning.md:175 +msgid "Points and Polygons" +msgstr "ポイントとポリゴン" + +#: src/SUMMARY.md:161 msgid "Day 3: Afternoon" msgstr "Day 3: PM" -#: src/SUMMARY.md:153 src/error-handling.md:1 +#: src/SUMMARY.md:163 src/error-handling.md:1 msgid "Error Handling" msgstr "エラー処理" -#: src/SUMMARY.md:154 src/error-handling/panics.md:1 +#: src/SUMMARY.md:164 src/error-handling/panics.md:1 msgid "Panics" msgstr "パニック(panic)" -#: src/SUMMARY.md:155 +#: src/SUMMARY.md:165 msgid "Catching Stack Unwinding" msgstr "スタックの巻き戻し" -#: src/SUMMARY.md:156 +#: src/SUMMARY.md:166 msgid "Structured Error Handling" msgstr "構造化されたエラー処理" -#: src/SUMMARY.md:157 +#: src/SUMMARY.md:167 msgid "Propagating Errors with ?" msgstr "?でエラーを伝播する" -#: src/SUMMARY.md:158 src/error-handling/converting-error-types.md:1 +#: src/SUMMARY.md:168 src/error-handling/converting-error-types.md:1 #: src/error-handling/converting-error-types-example.md:1 msgid "Converting Error Types" msgstr "エラーの型変換" -#: src/SUMMARY.md:160 src/error-handling/deriving-error-enums.md:1 +#: src/SUMMARY.md:170 src/error-handling/deriving-error-enums.md:1 msgid "Deriving Error Enums" msgstr "列挙型エラーの導出" -#: src/SUMMARY.md:161 src/error-handling/dynamic-errors.md:1 +#: src/SUMMARY.md:171 src/error-handling/dynamic-errors.md:1 msgid "Dynamic Error Types" msgstr "動的なエラー型" -#: src/SUMMARY.md:162 src/error-handling/error-contexts.md:1 +#: src/SUMMARY.md:172 src/error-handling/error-contexts.md:1 msgid "Adding Context to Errors" msgstr "コンテキストをエラーに追加" -#: src/SUMMARY.md:163 src/testing.md:1 +#: src/SUMMARY.md:173 src/testing.md:1 msgid "Testing" msgstr "テスト" -#: src/SUMMARY.md:164 src/testing/unit-tests.md:1 +#: src/SUMMARY.md:174 src/testing/unit-tests.md:1 msgid "Unit Tests" msgstr "ユニットテスト" -#: src/SUMMARY.md:165 src/testing/test-modules.md:1 +#: src/SUMMARY.md:175 src/testing/test-modules.md:1 msgid "Test Modules" msgstr "テストモジュール" -#: src/SUMMARY.md:166 src/testing/doc-tests.md:1 +#: src/SUMMARY.md:176 src/testing/doc-tests.md:1 msgid "Documentation Tests" msgstr "ドキュメンテーションテスト" -#: src/SUMMARY.md:167 src/testing/integration-tests.md:1 +#: src/SUMMARY.md:177 src/testing/integration-tests.md:1 msgid "Integration Tests" msgstr "インテグレーションテスト" -#: src/SUMMARY.md:168 src/bare-metal/useful-crates.md:1 +#: src/SUMMARY.md:178 src/bare-metal/useful-crates.md:1 msgid "Useful crates" msgstr "便利クレート" -#: src/SUMMARY.md:169 src/unsafe.md:1 +#: src/SUMMARY.md:179 src/unsafe.md:1 msgid "Unsafe Rust" msgstr "Unsafe Rust" -#: src/SUMMARY.md:170 src/unsafe/raw-pointers.md:1 +#: src/SUMMARY.md:180 src/unsafe/raw-pointers.md:1 msgid "Dereferencing Raw Pointers" msgstr "生ポインタの参照外し" -#: src/SUMMARY.md:171 src/unsafe/mutable-static-variables.md:1 +#: src/SUMMARY.md:181 src/unsafe/mutable-static-variables.md:1 msgid "Mutable Static Variables" msgstr "可変なstatic変数" -#: src/SUMMARY.md:172 src/unsafe/unions.md:1 +#: src/SUMMARY.md:182 src/unsafe/unions.md:1 msgid "Unions" msgstr "共用体" -#: src/SUMMARY.md:173 src/unsafe/calling-unsafe-functions.md:1 +#: src/SUMMARY.md:183 src/unsafe/calling-unsafe-functions.md:1 msgid "Calling Unsafe Functions" msgstr "Unsafe関数の呼び出し" -#: src/SUMMARY.md:174 src/unsafe/writing-unsafe-functions.md:1 +#: src/SUMMARY.md:184 src/unsafe/writing-unsafe-functions.md:1 msgid "Writing Unsafe Functions" msgstr "Unsafe関数の書き方" -#: src/SUMMARY.md:175 +#: src/SUMMARY.md:185 msgid "Extern Functions" msgstr "Extern関数" -#: src/SUMMARY.md:176 src/unsafe/unsafe-traits.md:1 +#: src/SUMMARY.md:186 src/unsafe/unsafe-traits.md:1 msgid "Implementing Unsafe Traits" msgstr "Unsafeなトレイトの実装" -#: src/SUMMARY.md:178 src/exercises/day-3/safe-ffi-wrapper.md:1 +#: src/SUMMARY.md:188 src/exercises/day-3/safe-ffi-wrapper.md:1 #: src/exercises/day-3/solutions-afternoon.md:3 msgid "Safe FFI Wrapper" msgstr "安全なFFIラッパ" -#: src/SUMMARY.md:181 src/SUMMARY.md:249 -#: src/running-the-course/course-structure.md:16 src/bare-metal/android.md:1 +#: src/SUMMARY.md:191 src/SUMMARY.md:261 src/bare-metal/android.md:1 msgid "Android" msgstr "Android" -#: src/SUMMARY.md:186 src/android/setup.md:1 +#: src/SUMMARY.md:196 src/android/setup.md:1 msgid "Setup" msgstr "セットアップ" -#: src/SUMMARY.md:187 src/android/build-rules.md:1 +#: src/SUMMARY.md:197 src/android/build-rules.md:1 msgid "Build Rules" msgstr "ビルドのルール" -#: src/SUMMARY.md:188 +#: src/SUMMARY.md:198 msgid "Binary" msgstr "バイナリ" -#: src/SUMMARY.md:189 +#: src/SUMMARY.md:199 msgid "Library" msgstr "ライブラリ" -#: src/SUMMARY.md:190 src/android/aidl.md:1 +#: src/SUMMARY.md:200 src/android/aidl.md:1 msgid "AIDL" msgstr "AIDL(Androidインターフェイス定義言語)" -#: src/SUMMARY.md:191 +#: src/SUMMARY.md:201 msgid "Interface" msgstr "インターフェイス" -#: src/SUMMARY.md:192 +#: src/SUMMARY.md:202 msgid "Implementation" msgstr "実装" -#: src/SUMMARY.md:193 +#: src/SUMMARY.md:203 msgid "Server" msgstr "サーバ" -#: src/SUMMARY.md:194 src/android/aidl/deploy.md:1 +#: src/SUMMARY.md:204 src/android/aidl/deploy.md:1 msgid "Deploy" msgstr "デプロイ" -#: src/SUMMARY.md:195 +#: src/SUMMARY.md:205 msgid "Client" msgstr "クライアント" -#: src/SUMMARY.md:196 src/android/aidl/changing.md:1 +#: src/SUMMARY.md:206 src/android/aidl/changing.md:1 msgid "Changing API" msgstr "APIの変更" -#: src/SUMMARY.md:197 src/SUMMARY.md:240 src/android/logging.md:1 +#: src/SUMMARY.md:207 src/SUMMARY.md:251 src/android/logging.md:1 #: src/bare-metal/aps/logging.md:1 msgid "Logging" msgstr "ログ出力" -#: src/SUMMARY.md:198 src/android/interoperability.md:1 +#: src/SUMMARY.md:208 src/android/interoperability.md:1 msgid "Interoperability" msgstr "相互運用性" -#: src/SUMMARY.md:199 +#: src/SUMMARY.md:209 msgid "With C" msgstr "C" -#: src/SUMMARY.md:200 +#: src/SUMMARY.md:210 msgid "Calling C with Bindgen" msgstr "BindgenによるCの呼び出し" -#: src/SUMMARY.md:201 +#: src/SUMMARY.md:211 msgid "Calling Rust from C" msgstr "CからRust呼び出し" -#: src/SUMMARY.md:202 src/android/interoperability/cpp.md:1 +#: src/SUMMARY.md:212 src/android/interoperability/cpp.md:1 msgid "With C++" msgstr "C++" -#: src/SUMMARY.md:203 +#: src/SUMMARY.md:213 msgid "With Java" msgstr "Java" -#: src/SUMMARY.md:207 +#: src/SUMMARY.md:217 msgid "Bare Metal: Morning" msgstr "ベアメタル: AM" -#: src/SUMMARY.md:212 +#: src/SUMMARY.md:222 msgid "no_std" msgstr "no_std" -#: src/SUMMARY.md:213 +#: src/SUMMARY.md:223 msgid "A Minimal Example" msgstr "例" -#: src/SUMMARY.md:214 +#: src/SUMMARY.md:224 msgid "alloc" msgstr "alloc" -#: src/SUMMARY.md:215 src/bare-metal/microcontrollers.md:1 +#: src/SUMMARY.md:225 src/bare-metal/microcontrollers.md:1 msgid "Microcontrollers" msgstr "マイクロコントローラ" -#: src/SUMMARY.md:216 src/bare-metal/microcontrollers/mmio.md:1 +#: src/SUMMARY.md:226 src/bare-metal/microcontrollers/mmio.md:1 msgid "Raw MMIO" msgstr "生MMIO(メモリマップトI/O)" -#: src/SUMMARY.md:217 +#: src/SUMMARY.md:227 msgid "PACs" msgstr "PACs" -#: src/SUMMARY.md:218 +#: src/SUMMARY.md:228 msgid "HAL Crates" msgstr "HALクレート" -#: src/SUMMARY.md:219 +#: src/SUMMARY.md:229 msgid "Board Support Crates" msgstr "ボードサポートクレート" -#: src/SUMMARY.md:220 +#: src/SUMMARY.md:230 msgid "The Type State Pattern" msgstr "タイプステートパターン" -#: src/SUMMARY.md:221 +#: src/SUMMARY.md:231 msgid "embedded-hal" msgstr "embedded-hal" -#: src/SUMMARY.md:222 +#: src/SUMMARY.md:232 msgid "probe-rs, cargo-embed" msgstr "probe-rs, cargo-embed" -#: src/SUMMARY.md:223 src/bare-metal/microcontrollers/debugging.md:1 +#: src/SUMMARY.md:233 src/bare-metal/microcontrollers/debugging.md:1 msgid "Debugging" msgstr "デバッグ" -#: src/SUMMARY.md:224 src/SUMMARY.md:242 +#: src/SUMMARY.md:234 src/SUMMARY.md:254 msgid "Other Projects" msgstr "他のプロジェクト" -#: src/SUMMARY.md:226 src/exercises/bare-metal/compass.md:1 +#: src/SUMMARY.md:236 src/exercises/bare-metal/compass.md:1 #: src/exercises/bare-metal/solutions-morning.md:3 msgid "Compass" msgstr "コンパス" -#: src/SUMMARY.md:228 +#: src/SUMMARY.md:238 msgid "Bare Metal: Afternoon" msgstr "ベアメタル: PM" -#: src/SUMMARY.md:230 +#: src/SUMMARY.md:240 msgid "Application Processors" msgstr "アプリケーションプロセッサ" -#: src/SUMMARY.md:231 +#: src/SUMMARY.md:241 src/bare-metal/aps/entry-point.md:1 +msgid "Getting Ready to Rust" +msgstr "" + +#: src/SUMMARY.md:242 msgid "Inline Assembly" msgstr "インラインアセンブリ" -#: src/SUMMARY.md:232 +#: src/SUMMARY.md:243 msgid "MMIO" msgstr "MMIO" -#: src/SUMMARY.md:233 +#: src/SUMMARY.md:244 msgid "Let's Write a UART Driver" msgstr "UARTドライバを書いてみよう" -#: src/SUMMARY.md:234 +#: src/SUMMARY.md:245 msgid "More Traits" msgstr "他のトレイト" -#: src/SUMMARY.md:235 +#: src/SUMMARY.md:246 msgid "A Better UART Driver" msgstr "UARTドライバの改善" -#: src/SUMMARY.md:236 src/bare-metal/aps/better-uart/bitflags.md:1 +#: src/SUMMARY.md:247 src/bare-metal/aps/better-uart/bitflags.md:1 msgid "Bitflags" msgstr "ビットフラッグ" -#: src/SUMMARY.md:237 +#: src/SUMMARY.md:248 msgid "Multiple Registers" msgstr "複数のレジスタ" -#: src/SUMMARY.md:238 src/bare-metal/aps/better-uart/driver.md:1 +#: src/SUMMARY.md:249 src/bare-metal/aps/better-uart/driver.md:1 msgid "Driver" msgstr "ドライバ" -#: src/SUMMARY.md:239 src/SUMMARY.md:241 +#: src/SUMMARY.md:250 src/SUMMARY.md:252 msgid "Using It" msgstr "使用例" -#: src/SUMMARY.md:243 +#: src/SUMMARY.md:253 src/bare-metal/aps/exceptions.md:1 +#, fuzzy +msgid "Exceptions" +msgstr "関数" + +#: src/SUMMARY.md:255 msgid "Useful Crates" msgstr "便利クレート" -#: src/SUMMARY.md:244 +#: src/SUMMARY.md:256 msgid "zerocopy" msgstr "zerocopy" -#: src/SUMMARY.md:245 +#: src/SUMMARY.md:257 msgid "aarch64-paging" msgstr "aarch64-paging" -#: src/SUMMARY.md:246 +#: src/SUMMARY.md:258 msgid "buddy_system_allocator" msgstr "buddy_system_allocator" -#: src/SUMMARY.md:247 +#: src/SUMMARY.md:259 msgid "tinyvec" msgstr "tinyvec" -#: src/SUMMARY.md:248 +#: src/SUMMARY.md:260 msgid "spin" msgstr "spin" -#: src/SUMMARY.md:250 src/bare-metal/android/vmbase.md:1 +#: src/SUMMARY.md:262 src/bare-metal/android/vmbase.md:1 msgid "vmbase" msgstr "vmbase" -#: src/SUMMARY.md:252 +#: src/SUMMARY.md:264 msgid "RTC Driver" msgstr "RTC(リアルタイムクロック)ドライバ" -#: src/SUMMARY.md:255 +#: src/SUMMARY.md:267 msgid "Concurrency: Morning" msgstr "並行性: AM" -#: src/SUMMARY.md:260 src/concurrency/threads.md:1 +#: src/SUMMARY.md:272 src/concurrency/threads.md:1 msgid "Threads" msgstr "スレッド" -#: src/SUMMARY.md:261 src/concurrency/scoped-threads.md:1 +#: src/SUMMARY.md:273 src/concurrency/scoped-threads.md:1 msgid "Scoped Threads" msgstr "スコープ付きスレッド" -#: src/SUMMARY.md:262 src/concurrency/channels.md:1 +#: src/SUMMARY.md:274 src/concurrency/channels.md:1 msgid "Channels" msgstr "チャネル" -#: src/SUMMARY.md:263 src/concurrency/channels/unbounded.md:1 +#: src/SUMMARY.md:275 src/concurrency/channels/unbounded.md:1 msgid "Unbounded Channels" msgstr "Unboundedチャネル" -#: src/SUMMARY.md:264 src/concurrency/channels/bounded.md:1 +#: src/SUMMARY.md:276 src/concurrency/channels/bounded.md:1 msgid "Bounded Channels" msgstr "Boundedチャネル" -#: src/SUMMARY.md:265 +#: src/SUMMARY.md:277 msgid "Send and Sync" msgstr "SendとSync" -#: src/SUMMARY.md:265 +#: src/SUMMARY.md:277 msgid "Send" msgstr "Send" -#: src/SUMMARY.md:265 +#: src/SUMMARY.md:277 msgid "Sync" msgstr "Sync" -#: src/SUMMARY.md:268 src/concurrency/send-sync/examples.md:1 +#: src/SUMMARY.md:280 src/concurrency/send-sync/examples.md:1 msgid "Examples" msgstr "例" -#: src/SUMMARY.md:269 src/concurrency/shared_state.md:1 +#: src/SUMMARY.md:281 src/concurrency/shared_state.md:1 msgid "Shared State" msgstr "状態共有" -#: src/SUMMARY.md:270 +#: src/SUMMARY.md:282 msgid "Arc" msgstr "Arc" -#: src/SUMMARY.md:271 +#: src/SUMMARY.md:283 msgid "Mutex" msgstr "Mutex" -#: src/SUMMARY.md:274 src/SUMMARY.md:294 +#: src/SUMMARY.md:286 src/SUMMARY.md:307 #: src/exercises/concurrency/dining-philosophers.md:1 #: src/exercises/concurrency/solutions-morning.md:3 msgid "Dining Philosophers" msgstr "食事する哲学者" -#: src/SUMMARY.md:275 src/exercises/concurrency/link-checker.md:1 +#: src/SUMMARY.md:287 src/exercises/concurrency/link-checker.md:1 msgid "Multi-threaded Link Checker" msgstr "マルチスレッド・リンクチェッカー" -#: src/SUMMARY.md:277 +#: src/SUMMARY.md:289 msgid "Concurrency: Afternoon" msgstr "並行性: PM" -#: src/SUMMARY.md:279 +#: src/SUMMARY.md:291 msgid "Async Basics" msgstr "Asyncの基礎" -#: src/SUMMARY.md:280 +#: src/SUMMARY.md:292 msgid "async/await" msgstr "async/await" -#: src/SUMMARY.md:281 src/async/futures.md:1 +#: src/SUMMARY.md:293 src/async/futures.md:1 msgid "Futures" msgstr "Future" -#: src/SUMMARY.md:282 src/async/runtimes.md:1 +#: src/SUMMARY.md:294 src/async/runtimes.md:1 msgid "Runtimes" msgstr "ランタイム" -#: src/SUMMARY.md:283 src/async/runtimes/tokio.md:1 +#: src/SUMMARY.md:295 src/async/runtimes/tokio.md:1 msgid "Tokio" msgstr "Tokio" -#: src/SUMMARY.md:284 src/exercises/concurrency/link-checker.md:106 -#: src/exercises/concurrency/chat-app.md:140 src/async/tasks.md:1 +#: src/SUMMARY.md:296 src/exercises/concurrency/link-checker.md:126 +#: src/async/tasks.md:1 src/exercises/concurrency/chat-app.md:140 msgid "Tasks" msgstr "タスク" -#: src/SUMMARY.md:285 src/async/channels.md:1 +#: src/SUMMARY.md:297 src/async/channels.md:1 msgid "Async Channels" msgstr "Asyncチャネル" -#: src/SUMMARY.md:287 src/async/control-flow/join.md:1 +#: src/SUMMARY.md:299 src/async/control-flow/join.md:1 msgid "Join" msgstr "" -#: src/SUMMARY.md:288 src/async/control-flow/select.md:1 +#: src/SUMMARY.md:300 src/async/control-flow/select.md:1 msgid "Select" msgstr "" -#: src/SUMMARY.md:289 +#: src/SUMMARY.md:301 msgid "Pitfalls" msgstr "落とし穴" -#: src/SUMMARY.md:290 +#: src/SUMMARY.md:302 msgid "Blocking the Executor" msgstr "エグゼキュータのブロッキング" -#: src/SUMMARY.md:291 src/async/pitfalls/pin.md:1 +#: src/SUMMARY.md:303 src/async/pitfalls/pin.md:1 msgid "Pin" msgstr "Pin" -#: src/SUMMARY.md:292 src/async/pitfalls/async-traits.md:1 +#: src/SUMMARY.md:304 src/async/pitfalls/async-traits.md:1 msgid "Async Traits" msgstr "Asyncトレイト" -#: src/SUMMARY.md:295 src/exercises/concurrency/chat-app.md:1 -#: src/exercises/concurrency/solutions-afternoon.md:113 +#: src/SUMMARY.md:305 src/async/pitfalls/cancellation.md:1 +#, fuzzy +msgid "Cancellation" +msgstr "インストール" + +#: src/SUMMARY.md:308 src/exercises/concurrency/chat-app.md:1 +#: src/exercises/concurrency/solutions-afternoon.md:119 msgid "Broadcast Chat Application" msgstr "ブロードキャスト・チャットアプリ" -#: src/SUMMARY.md:298 +#: src/SUMMARY.md:311 msgid "Final Words" msgstr "最後に" -#: src/SUMMARY.md:302 src/thanks.md:1 +#: src/SUMMARY.md:315 src/thanks.md:1 msgid "Thanks!" msgstr "ありがとうございました!" -#: src/SUMMARY.md:303 +#: src/SUMMARY.md:316 msgid "Other Resources" msgstr "参考資料" -#: src/SUMMARY.md:304 src/credits.md:1 +#: src/SUMMARY.md:317 src/credits.md:1 msgid "Credits" msgstr "クレジット" -#: src/SUMMARY.md:307 src/exercises/solutions.md:1 +#: src/SUMMARY.md:320 src/exercises/solutions.md:1 msgid "Solutions" msgstr "解答" -#: src/SUMMARY.md:312 +#: src/SUMMARY.md:325 msgid "Day 1 Morning" msgstr "Day 1 AM" -#: src/SUMMARY.md:313 +#: src/SUMMARY.md:326 msgid "Day 1 Afternoon" msgstr "Day 1 PM" -#: src/SUMMARY.md:314 +#: src/SUMMARY.md:327 msgid "Day 2 Morning" msgstr "Day 2 AM" -#: src/SUMMARY.md:315 +#: src/SUMMARY.md:328 msgid "Day 2 Afternoon" msgstr "Day 2 PM" -#: src/SUMMARY.md:316 +#: src/SUMMARY.md:329 msgid "Day 3 Morning" msgstr "Day 3 AM" -#: src/SUMMARY.md:317 +#: src/SUMMARY.md:330 msgid "Day 3 Afternoon" msgstr "Day 3 PM" -#: src/SUMMARY.md:318 +#: src/SUMMARY.md:331 msgid "Bare Metal Rust Morning" msgstr "ベアメタルRust AM" -#: src/SUMMARY.md:319 src/exercises/bare-metal/solutions-afternoon.md:1 +#: src/SUMMARY.md:332 src/exercises/bare-metal/solutions-afternoon.md:1 msgid "Bare Metal Rust Afternoon" msgstr "ベアメタルRust PM" -#: src/SUMMARY.md:320 +#: src/SUMMARY.md:333 msgid "Concurrency Morning" msgstr "並行性 AM" -#: src/SUMMARY.md:321 +#: src/SUMMARY.md:334 msgid "Concurrency Afternoon" msgstr "並行性 PM" -#: src/welcome.md:3 -msgid "" -"[![Build workflow](https://img.shields.io/github/actions/workflow/status/" -"google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" -"google/comprehensive-rust/actions/workflows/build.yml?query=branch%3Amain)" -msgstr "" - -#: src/welcome.md:3 -msgid "Build workflow" -msgstr "" - -#: src/welcome.md:3 +#: src/index.md:3 +#, fuzzy msgid "" "[![Build workflow](https://img.shields.io/github/actions/workflow/status/" "google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" "google/comprehensive-rust/actions/workflows/build.yml?query=branch%3Amain) [!" "[GitHub contributors](https://img.shields.io/github/contributors/google/" "comprehensive-rust?style=flat-square)](https://github.com/google/" -"comprehensive-rust/graphs/contributors)" +"comprehensive-rust/graphs/contributors) [![GitHub stars](https://img.shields." +"io/github/stars/google/comprehensive-rust?style=flat-square)](https://github." +"com/google/comprehensive-rust/stargazers)" msgstr "" "[![Build workflow](https://img.shields.io/github/actions/workflow/status/" "google/comprehensive-rust/build.yml?style=flat-square)](https://github.com/" @@ -1036,50 +1055,18 @@ msgstr "" "comprehensive-rust?style=flat-square)](https://github.com/google/" "comprehensive-rust/graphs/contributors)" -#: src/welcome.md:4 -msgid "GitHub contributors" -msgstr "" - -#: src/welcome.md:4 +#: src/index.md:7 +#, fuzzy msgid "" -"[![GitHub contributors](https://img.shields.io/github/contributors/google/" -"comprehensive-rust?style=flat-square)](https://github.com/google/" -"comprehensive-rust/graphs/contributors) [![GitHub stars](https://img.shields." -"io/github/stars/google/comprehensive-rust?style=flat-square)](https://github." -"com/google/comprehensive-rust/stargazers)" -msgstr "" -"[![GitHub contributors](https://img.shields.io/github/contributors/google/" -"comprehensive-rust?style=flat-square)](https://github.com/google/" -"comprehensive-rust/graphs/contributors) [![GitHub stars](https://img.shields." -"io/github/stars/google/comprehensive-rust?style=flat-square)](https://github." -"com/google/comprehensive-rust/stargazers)" - -#: src/welcome.md:5 -msgid "GitHub stars" -msgstr "" - -#: src/welcome.md:5 -msgid "" -"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" -"rust?style=flat-square)](https://github.com/google/comprehensive-rust/" -"stargazers)" -msgstr "" -"[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" -"rust?style=flat-square)](https://github.com/google/comprehensive-rust/" -"stargazers)" - -#: src/welcome.md:7 -msgid "" -"This is a three day Rust course developed by the Android team. The course " -"covers the full spectrum of Rust, from basic syntax to advanced topics like " -"generics and error handling. It also includes Android-specific content on " -"the last day." +"This is a free Rust course developed by the Android team at Google. The " +"course covers the full spectrum of Rust, from basic syntax to advanced " +"topics like generics and error handling." msgstr "" "この資料は、GoogleのAndroidチームによって開発された3日間のRust講座です。本講" "座では、基本構文からジェネリクスやエラー処理など、幅広い内容をカバーします。" "また、最終日にはAndroid専用の内容も含まれています。" -#: src/welcome.md:11 +#: src/index.md:11 msgid "" "The goal of the course is to teach you Rust. We assume you don't know " "anything about Rust and hope to:" @@ -1087,28 +1074,31 @@ msgstr "" "本講座の目的は、Rustを教える事です。Rustに関する前提知識は不要としており、次" "の目標を設定しています:" -#: src/welcome.md:14 +#: src/index.md:14 msgid "Give you a comprehensive understanding of the Rust syntax and language." msgstr "Rustの基本構文と言語についての理解を深める。" -#: src/welcome.md:15 +#: src/index.md:15 msgid "Enable you to modify existing programs and write new programs in Rust." msgstr "既存のプログラムを修正したり、新規プログラムをRustで書けるようにする。" -#: src/welcome.md:16 +#: src/index.md:16 msgid "Show you common Rust idioms." msgstr "一般的なRustのイディオムを紹介する。" -#: src/welcome.md:18 +#: src/index.md:18 +msgid "We call the first three course days Rust Fundamentals." +msgstr "" + +#: src/index.md:20 #, fuzzy msgid "" -"The first three days show you the fundamentals of Rust. Following this, " -"you're invited to dive into one or more specialized topics:" +"Building on this, you're invited to dive into one or more specialized topics:" msgstr "" "最初の3日間は、Rustの基礎を学びます。その後、より専門的なトピックに進む事がで" "きます:" -#: src/welcome.md:21 +#: src/index.md:22 #, fuzzy msgid "" "[Android](android.md): a half-day course on using Rust for Android platform " @@ -1117,10 +1107,10 @@ msgstr "" "[Android](android.md): Androidオープンソースプラットフォーム(AOSP)でRustを" "使用するための半日講座。C、C++、およびJavaとの相互運用性も含まれます。" -#: src/welcome.md:23 +#: src/index.md:24 #, fuzzy msgid "" -"[Bare-metal](bare-metal.md): a full day class on using Rust for bare-metal " +"[Bare-metal](bare-metal.md): a whole-day class on using Rust for bare-metal " "(embedded) development. Both microcontrollers and application processors are " "covered." msgstr "" @@ -1128,10 +1118,10 @@ msgstr "" "の1日講座。マイクロコントローラとアプリケーションプロセッサの両方が対象となり" "ます。" -#: src/welcome.md:26 +#: src/index.md:27 #, fuzzy msgid "" -"[Concurrency](concurrency.md): a full day class on concurrency in Rust. We " +"[Concurrency](concurrency.md): a whole-day class on concurrency in Rust. We " "cover both classical concurrency (preemptively scheduling using threads and " "mutexes) and async/await concurrency (cooperative multitasking using " "futures)." @@ -1140,11 +1130,11 @@ msgstr "" "ドとミューテックスを用いたプリエンプティブなスケジューリング)と、async/await" "を使用した並行性(futuresを用いた協調的マルチタスク)がカバーされます。" -#: src/welcome.md:32 +#: src/index.md:33 msgid "Non-Goals" msgstr "本講座の対象外" -#: src/welcome.md:34 +#: src/index.md:35 msgid "" "Rust is a large language and we won't be able to cover all of it in a few " "days. Some non-goals of this course are:" @@ -1152,9 +1142,10 @@ msgstr "" "Rustは非常に汎用性の高い言語であり、数日で全てを網羅する事はできません。本講" "座の目標として設定されていないものには、以下のようなものがあります:" -#: src/welcome.md:37 +#: src/index.md:38 +#, fuzzy msgid "" -"Learn how to develop macros, please see [Chapter 19.5 in the Rust Book]" +"Learning how to develop macros: please see [Chapter 19.5 in the Rust Book]" "(https://doc.rust-lang.org/book/ch19-06-macros.html) and [Rust by Example]" "(https://doc.rust-lang.org/rust-by-example/macros.html) instead." msgstr "" @@ -1163,29 +1154,31 @@ msgstr "" "版 Ch.17](http://doc.rust-jp.rs/rust-by-example-ja/macros.html)を参照してくだ" "さい。" -#: src/welcome.md:41 +#: src/index.md:42 msgid "Assumptions" msgstr "前提知識" -#: src/welcome.md:43 +#: src/index.md:44 +#, fuzzy msgid "" "The course assumes that you already know how to program. Rust is a " -"statically typed language and we will sometimes make comparisons with C and " +"statically-typed language and we will sometimes make comparisons with C and " "C++ to better explain or contrast the Rust approach." msgstr "" "本講座では、既にプログラミングの知識がある事を前提としています。Rustは静的型" "付け言語であり、Rustのアプローチをより分かりやすく説明するために、時折CやC+" "+との比較を行います。" -#: src/welcome.md:47 +#: src/index.md:48 +#, fuzzy msgid "" -"If you know how to program in a dynamically typed language such as Python or " +"If you know how to program in a dynamically-typed language such as Python or " "JavaScript, then you will be able to follow along just fine too." msgstr "" "もし受講者の知識がPythonやJavaScriptなどの動的型付け言語に限定されている場合" "でも、本講座の受講は可能です。" -#: src/welcome.md:52 +#: src/index.md:53 msgid "" "This is an example of a _speaker note_. We will use these to add additional " "information to the slides. This could be key points which the instructor " @@ -1304,15 +1297,19 @@ msgid "The course is fast paced and covers a lot of ground:" msgstr "本講座はペースが早く、多くの内容をカバーします:" #: src/running-the-course/course-structure.md:7 -msgid "Day 1: Basic Rust, ownership and the borrow checker." -msgstr "Day 1: Rustの基本、所有権と借用チェッカー" +msgid "Day 1: Basic Rust, syntax, control flow, creating and consuming values." +msgstr "" #: src/running-the-course/course-structure.md:8 -msgid "Day 2: Compound data types, pattern matching, the standard library." +#, fuzzy +msgid "" +"Day 2: Memory management, ownership, compound data types, and the standard " +"library." msgstr "Day 2: 複合データ型、パターンマッチング、標準ライブラリ" #: src/running-the-course/course-structure.md:9 -msgid "Day 3: Traits and generics, error handling, testing, unsafe Rust." +#, fuzzy +msgid "Day 3: Generics, traits, error handling, testing, and unsafe Rust." msgstr "Day 3: トレイトとジェネリクス、エラー処理、テスト、unsafe Rust" #: src/running-the-course/course-structure.md:11 @@ -1327,12 +1324,17 @@ msgstr "" "Rustの基礎に関する3日間の講座に加え、いくつかのより専門的なトピックも用意され" "ています:" +#: src/running-the-course/course-structure.md:16 +#, fuzzy +msgid "Rust in Android" +msgstr "Android" + #: src/running-the-course/course-structure.md:18 #, fuzzy msgid "" -"The [Android Deep Dive](../android.md) is a half-day course on using Rust " -"for Android platform development. This includes interoperability with C, C+" -"+, and Java." +"The [Rust in Android](../android.md) deep dive is a half-day course on using " +"Rust for Android platform development. This includes interoperability with " +"C, C++, and Java." msgstr "" "[Android編](../android.md)は、Androidオープンソースプラットフォーム(AOSP)で" "Rustを使用するための半日程度の講座です。C、C++、およびJavaとの相互運用性も含" @@ -1364,14 +1366,16 @@ msgstr "" "確認してください。" #: src/running-the-course/course-structure.md:34 -msgid "Bare-Metal" +#, fuzzy +msgid "Bare-Metal Rust" msgstr "ベアメタル" #: src/running-the-course/course-structure.md:36 +#, fuzzy msgid "" -"The [Bare-Metal Deep Dive](../bare-metal.md): a full day class on using Rust " -"for bare-metal (embedded) development. Both microcontrollers and application " -"processors are covered." +"The [Bare-Metal Rust](../bare-metal.md) deep dive is a full day class on " +"using Rust for bare-metal (embedded) development. Both microcontrollers and " +"application processors are covered." msgstr "" "[ベアメタル編](../bare-metal.md)は、ベアメタル(組み込み)開発でRustを使用す" "るための1日講座です。マイクロコントローラとアプリケーションプロセッサの両方が" @@ -1389,13 +1393,15 @@ msgstr "" "明されているように、複数のパッケージをインストールする必要があります。" #: src/running-the-course/course-structure.md:45 -msgid "Concurrency" -msgstr "並行性" +#, fuzzy +msgid "Concurrency in Rust" +msgstr "Rustでの並行性へようこそ" #: src/running-the-course/course-structure.md:47 +#, fuzzy msgid "" -"The [Concurrency Deep Dive](../concurrency.md) is a full day class on " -"classical as well as `async`/`await` concurrency." +"The [Concurrency in Rust](../concurrency.md) deep dive is a full day class " +"on classical as well as `async`/`await` concurrency." msgstr "" "[並行性編](../concurrency.md) は、並行性とasync/awaitを使用した並行性について" "の1日講座です。" @@ -1476,8 +1482,9 @@ msgstr "本資料は、ボランティアによって翻訳されています: #: src/running-the-course/translations.md:6 msgid "" "[Brazilian Portuguese](https://google.github.io/comprehensive-rust/pt-BR/) " -"by [@rastringer](https://github.com/rastringer) and [@hugojacob](https://" -"github.com/hugojacob)." +"by [@rastringer](https://github.com/rastringer), [@hugojacob](https://github." +"com/hugojacob), [@joaovicmendes](https://github.com/joaovicmendes) and " +"[@henrif75](https://github.com/henrif75)." msgstr "" #: src/running-the-course/translations.md:7 @@ -1493,6 +1500,42 @@ msgid "" msgstr "画面右上の言語切り替えボタンから、切り替えを行なってください。" #: src/running-the-course/translations.md:11 +#, fuzzy +msgid "Incomplete Translations" +msgstr "翻訳" + +#: src/running-the-course/translations.md:13 +msgid "" +"There is a large number of in-progress translations. We link to the most " +"recently updated translations:" +msgstr "" + +#: src/running-the-course/translations.md:16 +msgid "" +"[Bengali](https://google.github.io/comprehensive-rust/bn/) by [@raselmandol]" +"(https://github.com/raselmandol)." +msgstr "" + +#: src/running-the-course/translations.md:17 +msgid "" +"[French](https://google.github.io/comprehensive-rust/fr/) by [@KookaS]" +"(https://github.com/KookaS) and [@vcaen](https://github.com/vcaen)." +msgstr "" + +#: src/running-the-course/translations.md:18 +msgid "" +"[German](https://google.github.io/comprehensive-rust/de/) by [@Throvn]" +"(https://github.com/Throvn) and [@ronaldfw](https://github.com/ronaldfw)." +msgstr "" + +#: src/running-the-course/translations.md:19 +msgid "" +"[Japanese](https://google.github.io/comprehensive-rust/ja/) by [@CoinEZ-JPN]" +"(https://github.com/CoinEZ) and [@momotaro1105](https://github.com/" +"momotaro1105)." +msgstr "" + +#: src/running-the-course/translations.md:21 msgid "" "If you want to help with this effort, please see [our instructions](https://" "github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md) for how to " @@ -1522,64 +1565,51 @@ msgid "Installation" msgstr "インストール" #: src/cargo.md:10 -msgid "Rustup (Recommended)" -msgstr "Rustup (推奨)" +msgid "**Please follow the instructions on .**" +msgstr "" #: src/cargo.md:12 +#, fuzzy msgid "" -"You can follow the instructions to install cargo and rust compiler, among " -"other standard ecosystem tools with the [rustup](https://rust-analyzer." -"github.io/) tool, which is maintained by the Rust Foundation." -msgstr "" -"[rustup](https://rust-analyzer.github.io/)ツールを使用して、cargoやrustコンパ" -"イラなどの標準エコシステムツールをインストールします。RustupはRust Foundation" -"によってメンテナンスされています。" - -#: src/cargo.md:14 -msgid "" -"Along with cargo and rustc, Rustup will install itself as a command line " -"utility that you can use to install/switch toolchains, setup cross " -"compilation, etc." +"This will give you the Cargo build tool (`cargo`) and the Rust compiler " +"(`rustc`). You will also get `rustup`, a command line utility that you can " +"use to install/switch toolchains, setup cross compilation, etc." msgstr "" "Rustupも、cargoやrustcと一緒にコマンドラインユーティリティとしてインストール" "されます。Rustupを使用することで、ツールチェーンのインストールや切り替え、ク" "ロスコンパイルの設定などが行えます。" #: src/cargo.md:16 -msgid "Package Managers" -msgstr "パッケージマネージャ" - -#: src/cargo.md:18 -msgid "Debian" -msgstr "" - -#: src/cargo.md:20 +#, fuzzy msgid "" -"On Debian/Ubuntu, you can install Cargo, the Rust source and the [Rust " -"formatter](https://github.com/rust-lang/rustfmt) with" +"On Debian/Ubuntu, you can also install Cargo, the Rust source and the [Rust " +"formatter](https://github.com/rust-lang/rustfmt) via `apt`. However, this " +"gets you an outdated rust version and may lead to unexpected behavior. The " +"command would be:" msgstr "" "Debian/Ubuntuを使用している場合、以下のコマンドを使ってcargo、rustのソース" "コード、[Rust formatter](https://github.com/rust-lang/rustfmt)をインストール" "します" -#: src/cargo.md:22 +#: src/cargo.md:18 msgid "" "```shell\n" -"$ sudo apt install cargo rust-src rustfmt\n" +"sudo apt install cargo rust-src rustfmt\n" "```" msgstr "" -#: src/cargo.md:26 +#: src/cargo.md:22 +#, fuzzy msgid "" -"This will allow \\[rust-analyzer\\]\\[1\\] to jump to the definitions. We " -"suggest using [VS Code](https://code.visualstudio.com/) to edit the code " -"(but any LSP compatible editor works)." +"We suggest using [VS Code](https://code.visualstudio.com/) to edit the code " +"(but any LSP compatible editor works with rust-analyzer[3](https://rust-" +"analyzer.github.io/))." msgstr "" "これで\\[rust-analyzer\\]\\[1\\]を使って定義に飛べるようになります。コードの" "編集には、[VS Code](https://code.visualstudio.com/)を推奨しています(ただし、" "LSP互換エディタならどれでも大丈夫です)。" -#: src/cargo.md:29 +#: src/cargo.md:24 msgid "" "Some folks also like to use the [JetBrains](https://www.jetbrains.com/" "clion/) family of IDEs, which do their own analysis but have their own " @@ -1611,11 +1641,12 @@ msgstr "" "ます。" #: src/cargo/rust-ecosystem.md:8 +#, fuzzy msgid "" "`cargo`: the Rust dependency manager and build tool. Cargo knows how to " -"download dependencies hosted on and it will pass them to " -"`rustc` when building your project. Cargo also comes with a built-in test " -"runner which is used to execute unit tests." +"download dependencies, usually hosted on , and it will " +"pass them to `rustc` when building your project. Cargo also comes with a " +"built-in test runner which is used to execute unit tests." msgstr "" "`cargo`: Rustのビルドシステム兼パッケージマネージャです。" "でホストされている依存関係をダウンロードし、プロジェクトビルド時に`rustc`に渡" @@ -1669,6 +1700,12 @@ msgstr "" #: src/cargo/rust-ecosystem.md:32 msgid "" +"Dependencies can also be resolved from alternative [registries](https://doc." +"rust-lang.org/cargo/reference/registries.html), git, folders, and more." +msgstr "" + +#: src/cargo/rust-ecosystem.md:34 +msgid "" "Rust also has [editions](https://doc.rust-lang.org/edition-guide/): the " "current edition is Rust 2021. Previous editions were Rust 2015 and Rust 2018." msgstr "" @@ -1676,13 +1713,13 @@ msgstr "" "があります:現在のエディションはRust2021です。以前はRust2015とRust2018でし" "た。" -#: src/cargo/rust-ecosystem.md:35 +#: src/cargo/rust-ecosystem.md:37 msgid "" "The editions are allowed to make backwards incompatible changes to the " "language." msgstr "エディションでは、後方非互換な変更を加える事ができます。" -#: src/cargo/rust-ecosystem.md:38 +#: src/cargo/rust-ecosystem.md:40 msgid "" "To prevent breaking code, editions are opt-in: you select the edition for " "your crate via the `Cargo.toml` file." @@ -1690,7 +1727,7 @@ msgstr "" "コードの破損を防ぐために、エディションはオプトイン方式です:`Cargo.toml`で、" "クレートに対して適用したいエディションを選択します。" -#: src/cargo/rust-ecosystem.md:41 +#: src/cargo/rust-ecosystem.md:43 msgid "" "To avoid splitting the ecosystem, Rust compilers can mix code written for " "different editions." @@ -1698,35 +1735,35 @@ msgstr "" "エコシステムの分断を避けるために、コンパイラは異なるエディションのコードを混" "在させる事ができます。" -#: src/cargo/rust-ecosystem.md:44 +#: src/cargo/rust-ecosystem.md:46 msgid "" "Mention that it is quite rare to ever use the compiler directly not through " "`cargo` (most users never do)." msgstr "" "コンパイラを直接使用する事は非常に稀であり、基本的には`cargo`を介します。" -#: src/cargo/rust-ecosystem.md:46 +#: src/cargo/rust-ecosystem.md:48 msgid "" "It might be worth alluding that Cargo itself is an extremely powerful and " "comprehensive tool. It is capable of many advanced features including but " "not limited to: " msgstr "`Cargo`は非常に包括的なツールであり、多くの機能を備えています:" -#: src/cargo/rust-ecosystem.md:47 +#: src/cargo/rust-ecosystem.md:49 msgid "Project/package structure" msgstr "プロジェクト・パッケージの構造管理" -#: src/cargo/rust-ecosystem.md:48 +#: src/cargo/rust-ecosystem.md:50 msgid "[workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)" msgstr "" "[workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)(ワー" "クスペース)" -#: src/cargo/rust-ecosystem.md:49 +#: src/cargo/rust-ecosystem.md:51 msgid "Dev Dependencies and Runtime Dependency management/caching" msgstr "開発用とランタイム用の依存関係管理・キャッシュ" -#: src/cargo/rust-ecosystem.md:50 +#: src/cargo/rust-ecosystem.md:52 msgid "" "[build scripting](https://doc.rust-lang.org/cargo/reference/build-scripts." "html)" @@ -1734,7 +1771,7 @@ msgstr "" "[build scripting](https://doc.rust-lang.org/cargo/reference/build-scripts." "html)(ビルドスクリプト)" -#: src/cargo/rust-ecosystem.md:51 +#: src/cargo/rust-ecosystem.md:53 msgid "" "[global installation](https://doc.rust-lang.org/cargo/commands/cargo-install." "html)" @@ -1742,7 +1779,7 @@ msgstr "" "[global installation](https://doc.rust-lang.org/cargo/commands/cargo-install." "html)" -#: src/cargo/rust-ecosystem.md:52 +#: src/cargo/rust-ecosystem.md:54 msgid "" "It is also extensible with sub command plugins as well (such as [cargo " "clippy](https://github.com/rust-lang/rust-clippy))." @@ -1750,7 +1787,7 @@ msgstr "" "[cargo clippy](https://github.com/rust-lang/rust-clippy)などのサブコマンドプ" "ラグインによる拡張" -#: src/cargo/rust-ecosystem.md:53 +#: src/cargo/rust-ecosystem.md:55 msgid "" "Read more from the [official Cargo Book](https://doc.rust-lang.org/cargo/)" msgstr "" @@ -1856,6 +1893,12 @@ msgid "" msgstr "" #: src/cargo/running-locally.md:15 +msgid "" +"You can use any later version too since Rust maintains backwards " +"compatibility." +msgstr "" + +#: src/cargo/running-locally.md:17 #, fuzzy msgid "" "With this in place, follow these steps to build a Rust binary from one of " @@ -1864,16 +1907,16 @@ msgstr "" "次に、本講座の例を参考にしながら、以下の手順に従ってRustのバイナリをビルドし" "てください:" -#: src/cargo/running-locally.md:18 +#: src/cargo/running-locally.md:20 msgid "Click the \"Copy to clipboard\" button on the example you want to copy." msgstr "「Copy to clipboard」でコードをコピー。" -#: src/cargo/running-locally.md:20 +#: src/cargo/running-locally.md:22 msgid "" "Use `cargo new exercise` to create a new `exercise/` directory for your code:" msgstr "`cargo new exercise`で`exercise/`ディレクトリを作成:" -#: src/cargo/running-locally.md:22 +#: src/cargo/running-locally.md:24 msgid "" "```shell\n" "$ cargo new exercise\n" @@ -1885,13 +1928,13 @@ msgstr "" " Created binary (application) `exercise` package\n" "```" -#: src/cargo/running-locally.md:27 +#: src/cargo/running-locally.md:29 msgid "" "Navigate into `exercise/` and use `cargo run` to build and run your binary:" msgstr "" "`exercise/`ディレクトリに移動し、`cargo run`でバイナリをビルドして実行:" -#: src/cargo/running-locally.md:29 +#: src/cargo/running-locally.md:31 msgid "" "```shell\n" "$ cd exercise\n" @@ -1911,7 +1954,7 @@ msgstr "" "Hello, world!\n" "```" -#: src/cargo/running-locally.md:38 +#: src/cargo/running-locally.md:40 msgid "" "Replace the boiler-plate code in `src/main.rs` with your own code. For " "example, using the example on the previous page, make `src/main.rs` look like" @@ -1919,7 +1962,7 @@ msgstr "" "`src/main.rs`のボイラープレートコードを、コピーしたコードで置き換えてくださ" "い。例えば、前のページの例を使った場合、`src/main.rs`は以下のようになります。" -#: src/cargo/running-locally.md:41 +#: src/cargo/running-locally.md:43 msgid "" "```rust\n" "fn main() {\n" @@ -1933,11 +1976,11 @@ msgstr "" "}\n" "```" -#: src/cargo/running-locally.md:47 +#: src/cargo/running-locally.md:49 msgid "Use `cargo run` to build and run your updated binary:" msgstr "`cargo run`で更新されたバイナリをビルドして実行:" -#: src/cargo/running-locally.md:49 +#: src/cargo/running-locally.md:51 msgid "" "```shell\n" "$ cargo run\n" @@ -1955,7 +1998,7 @@ msgstr "" "Edit me!\n" "```" -#: src/cargo/running-locally.md:57 +#: src/cargo/running-locally.md:59 msgid "" "Use `cargo check` to quickly check your project for errors, use `cargo " "build` to compile it without running it. You will find the output in `target/" @@ -1967,7 +2010,7 @@ msgstr "" "`target/debug/`に格納されます。最適化されたリリースビルドには`cargo build —" "release`を使い、ファイルは`target/release/`に格納されます。" -#: src/cargo/running-locally.md:62 +#: src/cargo/running-locally.md:64 msgid "" "You can add dependencies for your project by editing `Cargo.toml`. When you " "run `cargo` commands, it will automatically download and compile missing " @@ -1977,7 +2020,7 @@ msgstr "" "`cargo`コマンドを実行すると、自動的に不足している依存関係がダウンロードされて" "コンパイルされます。" -#: src/cargo/running-locally.md:70 +#: src/cargo/running-locally.md:72 msgid "" "Try to encourage the class participants to install Cargo and use a local " "editor. It will make their life easier since they will have a normal " @@ -1991,8 +2034,9 @@ msgid "Welcome to Day 1" msgstr "Day 1へようこそ" #: src/welcome-day-1.md:3 +#, fuzzy msgid "" -"This is the first day of Comprehensive Rust. We will cover a lot of ground " +"This is the first day of Rust Fundamentals. We will cover a lot of ground " "today:" msgstr "" "「Comprehensive Rust」の初日です。本日は多岐にわたる内容をカバーします:" @@ -2007,16 +2051,13 @@ msgstr "" #: src/welcome-day-1.md:9 msgid "" -"Memory management: stack vs heap, manual memory management, scope-based " -"memory management, and garbage collection." +"Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and " +"`continue`." msgstr "" -"メモリ管理: スタック vs ヒープ、手動でのメモリ管理、スコープに基づくメモリ管" -"理、ガベージコレクション。" #: src/welcome-day-1.md:12 -msgid "" -"Ownership: move semantics, copying and cloning, borrowing, and lifetimes." -msgstr "所有権: ムーブセマンティクス、コピーとクローン、借用、ライフタイム。" +msgid "Pattern matching: destructuring enums, structs, and arrays." +msgstr "" #: src/welcome-day-1.md:16 msgid "Please remind the students that:" @@ -2169,7 +2210,9 @@ msgid "High level of control." msgstr "高度な制御性" #: src/welcome-day-1/what-is-rust.md:25 -msgid "Can be scaled down to very constrained devices like mobile phones." +#, fuzzy +msgid "" +"Can be scaled down to very constrained devices such as microcontrollers." msgstr "携帯電話のようなデバイスにまでスケールダウンが可能" #: src/welcome-day-1/what-is-rust.md:26 @@ -2222,9 +2265,10 @@ msgstr "" "Rustの文字列はUTF-8でエンコードされ、どんなUnicode文字でも含む事ができます。" #: src/hello-world.md:22 +#, fuzzy msgid "" "This slide tries to make the students comfortable with Rust code. They will " -"see a ton of it over the next four days so we start small with something " +"see a ton of it over the next three days so we start small with something " "familiar." msgstr "" "このスライドの目的は、Rustのコードに慣れてもらう事です。この4日間で大量のRust" @@ -2234,8 +2278,7 @@ msgstr "" #, fuzzy msgid "" "Rust is very much like other languages in the C/C++/Java tradition. It is " -"imperative (not functional) and it doesn't try to reinvent things unless " -"absolutely necessary." +"imperative and it doesn't try to reinvent things unless absolutely necessary." msgstr "" "Rustは、C/C++/Java系統の言語によく似ています。Rustは、命令型(関数型ではな" "く)であり、必須でない限り機能の再発明はしません。" @@ -2267,6 +2310,14 @@ msgstr "" "ます。Rustのマクロは、実際には[部分的にしか衛生的](https://veykril.github.io/" "tlborm/decl-macros/minutiae/hygiene.html)ではありません。" +#: src/hello-world.md:40 +msgid "" +"Rust is multi-paradigm. For example, it has powerful [object-oriented " +"programming features](https://doc.rust-lang.org/book/ch17-00-oop.html), and, " +"while it is not a functional language, it includes a range of [functional " +"concepts](https://doc.rust-lang.org/book/ch13-00-functional-features.html)." +msgstr "" + #: src/hello-world/small-example.md:3 msgid "Here is a small example program in Rust:" msgstr "ここでは、Rustによる小さなサンプルプログラムを紹介します:" @@ -2356,6 +2407,12 @@ msgstr "" "`std::fmt`には、フォーマット機能のルールや構文が説明されています。受講者が標" "準ライブラリの検索に慣れておく事は重要です。" +#: src/hello-world/small-example.md:44 +msgid "" +"In a shell `rustup doc std::fmt` will open a browser on the local std::fmt " +"documentation" +msgstr "" + #: src/why-rust.md:3 msgid "Some unique selling points of Rust:" msgstr "Rustのユニークなセールスポイントをいくつか紹介します:" @@ -2504,15 +2561,19 @@ msgid "Array access is bounds checked." msgstr "配列へのアクセスには境界チェックが行われる。" #: src/why-rust/runtime.md:6 -msgid "Integer overflow is defined." +#, fuzzy +msgid "Integer overflow is defined (panic or wrap-around)." msgstr "整数オーバーフローの挙動が定義されている。" #: src/why-rust/runtime.md:12 +#, fuzzy msgid "" -"Integer overflow is defined via a compile-time flag. The options are either " -"a panic (a controlled crash of the program) or wrap-around semantics. By " -"default, you get panics in debug mode (`cargo build`) and wrap-around in " -"release mode (`cargo build --release`)." +"Integer overflow is defined via the [`overflow-checks`](https://doc.rust-" +"lang.org/rustc/codegen-options/index.html#overflow-checks) compile-time " +"flag. If enabled, the program will panic (a controlled crash of the " +"program), otherwise you get wrap-around semantics. By default, you get " +"panics in debug mode (`cargo build`) and wrap-around in release mode (`cargo " +"build --release`)." msgstr "" "整数オーバーフローは、コンパイル時のフラグで定義されます。選択肢として、パ" "ニック(プログラムの制御されたクラッシュ)またはラップアラウンドのセマンティ" @@ -2520,7 +2581,7 @@ msgstr "" "が発生し、リリースモード(`cargo build —release`)ではラップアラウンドが行わ" "れます。" -#: src/why-rust/runtime.md:17 +#: src/why-rust/runtime.md:18 msgid "" "Bounds checking cannot be disabled with a compiler flag. It can also not be " "disabled directly with the `unsafe` keyword. However, `unsafe` allows you to " @@ -2533,7 +2594,8 @@ msgstr "" "とができます。" #: src/why-rust/modern.md:3 -msgid "Rust is built with all the experience gained in the last 40 years." +#, fuzzy +msgid "Rust is built with all the experience gained in the last decades." msgstr "Rustは過去40年間の経験を基に構築されています。" #: src/why-rust/modern.md:5 @@ -2713,7 +2775,7 @@ msgid "`i8`, `i16`, `i32`, `i64`, `i128`, `isize`" msgstr "" #: src/basic-syntax/scalar-types.md:5 -msgid "`-10`, `0`, `1_000`, `123i64`" +msgid "`-10`, `0`, `1_000`, `123_i64`" msgstr "" #: src/basic-syntax/scalar-types.md:6 @@ -2725,7 +2787,7 @@ msgid "`u8`, `u16`, `u32`, `u64`, `u128`, `usize`" msgstr "" #: src/basic-syntax/scalar-types.md:6 -msgid "`0`, `123`, `10u16`" +msgid "`0`, `123`, `10_u16`" msgstr "" #: src/basic-syntax/scalar-types.md:7 @@ -2737,7 +2799,7 @@ msgid "`f32`, `f64`" msgstr "" #: src/basic-syntax/scalar-types.md:7 -msgid "`3.14`, `-10.0e20`, `2f32`" +msgid "`3.14`, `-10.0e20`, `2_f32`" msgstr "" #: src/basic-syntax/scalar-types.md:8 @@ -2789,11 +2851,11 @@ msgid "`isize` and `usize` are the width of a pointer," msgstr "" #: src/basic-syntax/scalar-types.md:16 -msgid "`char` is 32 bit wide," +msgid "`char` is 32 bits wide," msgstr "" #: src/basic-syntax/scalar-types.md:17 -msgid "`bool` is 8 bit wide." +msgid "`bool` is 8 bits wide." msgstr "" #: src/basic-syntax/scalar-types.md:21 @@ -2831,6 +2893,13 @@ msgid "" "```" msgstr "" +#: src/basic-syntax/scalar-types.md:43 +msgid "" +"All underscores in numbers can be left out, they are for legibility only. So " +"`1_000` can be written as `1000` (or `10_00`), and `123_i64` can be written " +"as `123i64`." +msgstr "" + #: src/basic-syntax/compound-types.md:5 msgid "Arrays" msgstr "" @@ -2891,10 +2960,10 @@ msgstr "" #: src/basic-syntax/compound-types.md:34 msgid "" -"Arrays have elements of the same type, `T`, and length, `N`, which is a " -"compile-time constant. Note that the length of the array is _part of its " -"type_, which means that `[u8; 3]` and `[u8; 4]` are considered two different " -"types." +"A value of the array type `[T; N]` holds `N` (a compile-time constant) " +"elements of the same type `T`. Note that the length of the array is _part of " +"its type_, which means that `[u8; 3]` and `[u8; 4]` are considered two " +"different types." msgstr "" #: src/basic-syntax/compound-types.md:38 @@ -3033,66 +3102,69 @@ msgstr "" msgid "" "```rust,editable\n" "fn main() {\n" -" let a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" +" let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60];\n" " println!(\"a: {a:?}\");\n" "\n" " let s: &[i32] = &a[2..4];\n" +"\n" " println!(\"s: {s:?}\");\n" "}\n" "```" msgstr "" -#: src/basic-syntax/slices.md:15 +#: src/basic-syntax/slices.md:16 msgid "Slices borrow data from the sliced type." msgstr "" -#: src/basic-syntax/slices.md:16 -msgid "Question: What happens if you modify `a[3]`?" +#: src/basic-syntax/slices.md:17 +msgid "Question: What happens if you modify `a[3]` right before printing `s`?" msgstr "" -#: src/basic-syntax/slices.md:20 +#: src/basic-syntax/slices.md:21 msgid "" "We create a slice by borrowing `a` and specifying the starting and ending " "indexes in brackets." msgstr "" -#: src/basic-syntax/slices.md:22 +#: src/basic-syntax/slices.md:23 msgid "" "If the slice starts at index 0, Rust’s range syntax allows us to drop the " "starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are " "identical." msgstr "" -#: src/basic-syntax/slices.md:24 +#: src/basic-syntax/slices.md:25 msgid "" "The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are " "identical." msgstr "" -#: src/basic-syntax/slices.md:26 +#: src/basic-syntax/slices.md:27 msgid "" "To easily create a slice of the full array, we can therefore use `&a[..]`." msgstr "" -#: src/basic-syntax/slices.md:28 +#: src/basic-syntax/slices.md:29 msgid "" "`s` is a reference to a slice of `i32`s. Notice that the type of `s` " "(`&[i32]`) no longer mentions the array length. This allows us to perform " "computation on slices of different sizes." msgstr "" -#: src/basic-syntax/slices.md:30 +#: src/basic-syntax/slices.md:31 msgid "" "Slices always borrow from another object. In this example, `a` has to remain " "'alive' (in scope) for at least as long as our slice. " msgstr "" -#: src/basic-syntax/slices.md:32 +#: src/basic-syntax/slices.md:33 msgid "" "The question about modifying `a[3]` can spark an interesting discussion, but " -"the answer is that for memory safety reasons you cannot do it through `a` " -"after you created a slice, but you can read the data from both `a` and `s` " -"safely. More details will be explained in the borrow checker section." +"the answer is that for memory safety reasons you cannot do it through `a` at " +"this point in the execution, but you can read the data from both `a` and `s` " +"safely. It works before you created the slice, and again after the " +"`println`, when the slice is no longer used. More details will be explained " +"in the borrow checker section." msgstr "" #: src/basic-syntax/string-slices.md:1 @@ -3288,6 +3360,13 @@ msgid "" "be addressed here." msgstr "" +#: src/basic-syntax/rustdoc.md:33 +msgid "" +"Rustdoc comments can contain code snippets that we can run and test using " +"`cargo test`. We will discuss these tests in the [Testing section](../" +"testing/doc-tests.html)." +msgstr "" + #: src/basic-syntax/methods.md:3 msgid "" "Methods are functions associated with a type. The `self` argument of a " @@ -3328,7 +3407,7 @@ msgid "" msgstr "" #: src/basic-syntax/methods.md:34 -msgid "Add a `Rectangle::new` constructor and call this from `main`:" +msgid "Add a static method called `Rectangle::new` and call this from `main`:" msgstr "" #: src/basic-syntax/methods.md:36 @@ -3342,8 +3421,16 @@ msgstr "" #: src/basic-syntax/methods.md:42 msgid "" -"Add a `Rectangle::new_square(width: u32)` constructor to illustrate that " -"constructors can take arbitrary parameters." +"While _technically_, Rust does not have custom constructors, static methods " +"are commonly used to initialize structs (but don't have to). The actual " +"constructor, `Rectangle { width, height }`, could be called directly. See " +"the [Rustnomicon](https://doc.rust-lang.org/nomicon/constructors.html)." +msgstr "" + +#: src/basic-syntax/methods.md:45 +msgid "" +"Add a `Rectangle::square(width: u32)` constructor to illustrate that such " +"static methods can take arbitrary parameters." msgstr "" #: src/basic-syntax/functions-interlude.md:1 @@ -3440,14 +3527,12 @@ msgid "" "their state if you navigate away from the page." msgstr "" -#: src/exercises/day-1/morning.md:22 src/exercises/day-1/afternoon.md:11 -#: src/exercises/day-2/morning.md:11 src/exercises/day-2/afternoon.md:7 -#: src/exercises/day-3/morning.md:7 src/exercises/bare-metal/morning.md:7 -#: src/exercises/bare-metal/afternoon.md:7 +#: src/exercises/day-1/morning.md:22 src/exercises/day-2/morning.md:11 +#: src/exercises/day-3/morning.md:9 src/exercises/bare-metal/morning.md:7 #: src/exercises/concurrency/morning.md:12 -#: src/exercises/concurrency/afternoon.md:13 msgid "" -"After looking at the exercises, you can look at the \\[solutions\\] provided." +"After looking at the exercises, you can look at the [solutions](solutions-" +"morning.md) provided." msgstr "" #: src/exercises/day-1/implicit-conversions.md:3 @@ -3560,7 +3645,7 @@ msgid "" "fn main() {\n" " let array = [10, 20, 30];\n" " print!(\"Iterating over array:\");\n" -" for n in array {\n" +" for n in &array {\n" " print!(\" {n}\");\n" " }\n" " println!();\n" @@ -3654,6 +3739,331 @@ msgid "" "[Solution](solutions-morning.md#arrays-and-for-loops) section." msgstr "" +#: src/exercises/day-1/for-loops.md:95 +msgid "" +"The use of the reference `&array` within `for n in &array` is a subtle " +"preview of issues of ownership that will come later in the afternoon." +msgstr "" + +#: src/exercises/day-1/for-loops.md:98 +msgid "Without the `&`..." +msgstr "" + +#: src/exercises/day-1/for-loops.md:99 +msgid "" +"The loop would have been one that consumes the array. This is a change " +"[introduced in the 2021 Edition](https://doc.rust-lang.org/edition-guide/" +"rust-2021/IntoIterator-for-arrays.html)." +msgstr "" + +#: src/exercises/day-1/for-loops.md:102 +msgid "" +"An implicit array copy would have occured. Since `i32` is a copy type, then " +"`[i32; 3]` is also a copy type." +msgstr "" + +#: src/control-flow.md:3 +msgid "" +"As we have seen, `if` is an expression in Rust. It is used to conditionally " +"evaluate one of two blocks, but the blocks can have a value which then " +"becomes the value of the `if` expression. Other control flow expressions " +"work similarly in Rust." +msgstr "" + +#: src/control-flow/blocks.md:3 +msgid "" +"A block in Rust contains a sequence of expressions. Each block has a value " +"and a type, which are those of the last expression of the block:" +msgstr "" + +#: src/control-flow/blocks.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = {\n" +" let y = 10;\n" +" println!(\"y: {y}\");\n" +" let z = {\n" +" let w = {\n" +" 3 + 4\n" +" };\n" +" println!(\"w: {w}\");\n" +" y * w\n" +" };\n" +" println!(\"z: {z}\");\n" +" z - y\n" +" };\n" +" println!(\"x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:26 +msgid "" +"If the last expression ends with `;`, then the resulting value and type is " +"`()`." +msgstr "" + +#: src/control-flow/blocks.md:28 +msgid "" +"The same rule is used for functions: the value of the function body is the " +"return value:" +msgstr "" + +#: src/control-flow/blocks.md:31 +msgid "" +"```rust,editable\n" +"fn double(x: i32) -> i32 {\n" +" x + x\n" +"}\n" +"\n" +"fn main() {\n" +" println!(\"doubled: {}\", double(7));\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/blocks.md:43 src/enums.md:34 src/enums/sizes.md:28 +#: src/pattern-matching.md:25 src/pattern-matching/match-guards.md:22 +#: src/structs.md:31 src/methods.md:30 src/methods/example.md:46 +msgid "Key Points:" +msgstr "" + +#: src/control-flow/blocks.md:44 +msgid "" +"The point of this slide is to show that blocks have a type and value in " +"Rust. " +msgstr "" + +#: src/control-flow/blocks.md:45 +msgid "" +"You can show how the value of the block changes by changing the last line in " +"the block. For instance, adding/removing a semicolon or using a `return`." +msgstr "" + +#: src/control-flow/if-expressions.md:1 +msgid "`if` expressions" +msgstr "" + +#: src/control-flow/if-expressions.md:3 +msgid "" +"You use [`if` expressions](https://doc.rust-lang.org/reference/expressions/" +"if-expr.html#if-expressions) exactly like `if` statements in other languages:" +msgstr "" + +#: src/control-flow/if-expressions.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" if x % 2 == 0 {\n" +" x = x / 2;\n" +" } else {\n" +" x = 3 * x + 1;\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:18 +msgid "" +"In addition, you can use `if` as an expression. The last expression of each " +"block becomes the value of the `if` expression:" +msgstr "" + +#: src/control-flow/if-expressions.md:22 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/if-expressions.md:35 +msgid "" +"Because `if` is an expression and must have a particular type, both of its " +"branch blocks must have the same type. Consider showing what happens if you " +"add `;` after `x / 2` in the second example." +msgstr "" + +#: src/control-flow/for-expressions.md:1 +msgid "`for` loops" +msgstr "" + +#: src/control-flow/for-expressions.md:3 +msgid "" +"The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) is closely " +"related to the [`while let` loop](while-let-expressions.md). It will " +"automatically call `into_iter()` on the expression and then iterate over it:" +msgstr "" + +#: src/control-flow/for-expressions.md:7 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +"\n" +" for x in v {\n" +" println!(\"x: {x}\");\n" +" }\n" +" \n" +" for i in (0..10).step_by(2) {\n" +" println!(\"i: {i}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/for-expressions.md:21 +msgid "You can use `break` and `continue` here as usual." +msgstr "" + +#: src/control-flow/for-expressions.md:25 +msgid "Index iteration is not a special syntax in Rust for just that case." +msgstr "" + +#: src/control-flow/for-expressions.md:26 +msgid "`(0..10)` is a range that implements an `Iterator` trait. " +msgstr "" + +#: src/control-flow/for-expressions.md:27 +msgid "" +"`step_by` is a method that returns another `Iterator` that skips every other " +"element. " +msgstr "" + +#: src/control-flow/for-expressions.md:28 +msgid "" +"Modify the elements in the vector and explain the compiler errors. Change " +"vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." +msgstr "" + +#: src/control-flow/while-expressions.md:1 +msgid "`while` loops" +msgstr "" + +#: src/control-flow/while-expressions.md:3 +msgid "" +"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-" +"expr.html#predicate-loops) works very similar to other languages:" +msgstr "" + +#: src/control-flow/while-expressions.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" while x != 1 {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/break-continue.md:1 +msgid "`break` and `continue`" +msgstr "" + +#: src/control-flow/break-continue.md:3 +msgid "" +"If you want to exit a loop early, use [`break`](https://doc.rust-lang.org/" +"reference/expressions/loop-expr.html#break-expressions)," +msgstr "" + +#: src/control-flow/break-continue.md:4 +msgid "" +"If you want to immediately start the next iteration use [`continue`](https://" +"doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)." +msgstr "" + +#: src/control-flow/break-continue.md:7 +msgid "" +"Both `continue` and `break` can optionally take a label argument which is " +"used to break out of nested loops:" +msgstr "" + +#: src/control-flow/break-continue.md:10 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +" 'outer: while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" let mut i = 0;\n" +" while i < x {\n" +" println!(\"x: {x}, i: {i}\");\n" +" i += 1;\n" +" if i == 3 {\n" +" break 'outer;\n" +" }\n" +" }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/break-continue.md:28 +msgid "" +"In this case we break the outer loop after 3 iterations of the inner loop." +msgstr "" + +#: src/control-flow/loop-expressions.md:1 +msgid "`loop` expressions" +msgstr "" + +#: src/control-flow/loop-expressions.md:3 +msgid "" +"Finally, there is a [`loop` keyword](https://doc.rust-lang.org/reference/" +"expressions/loop-expr.html#infinite-loops) which creates an endless loop." +msgstr "" + +#: src/control-flow/loop-expressions.md:6 +msgid "Here you must either `break` or `return` to stop the loop:" +msgstr "" + +#: src/control-flow/loop-expressions.md:8 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut x = 10;\n" +" loop {\n" +" x = if x % 2 == 0 {\n" +" x / 2\n" +" } else {\n" +" 3 * x + 1\n" +" };\n" +" if x == 1 {\n" +" break;\n" +" }\n" +" }\n" +" println!(\"Final x: {x}\");\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/loop-expressions.md:27 +msgid "Break the `loop` with a value (e.g. `break 8`) and print it out." +msgstr "" + +#: src/control-flow/loop-expressions.md:28 +msgid "" +"Note that `loop` is the only looping construct which returns a non-trivial " +"value. This is because it's guaranteed to be entered at least once (unlike " +"`while` and `for` loops)." +msgstr "" + #: src/basic-syntax/variables.md:3 msgid "" "Rust provides type safety via static typing. Variable bindings are immutable " @@ -3678,12 +4088,6 @@ msgid "" "types less and less as the course progresses." msgstr "" -#: src/basic-syntax/variables.md:18 -msgid "" -"Note that since `println!` is a macro, `x` is not moved, even using the " -"function like syntax of `println!(\"x: {}\", x)`" -msgstr "" - #: src/basic-syntax/type-inference.md:3 msgid "Rust will look at how the variable is _used_ to determine the type:" msgstr "" @@ -3750,8 +4154,10 @@ msgstr "" #: src/basic-syntax/type-inference.md:46 msgid "" "[`collect`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator." -"html#method.collect) relies on `FromIterator`, which [`HashSet`](https://doc." -"rust-lang.org/std/iter/trait.FromIterator.html) implements." +"html#method.collect) relies on [`FromIterator`](https://doc.rust-lang.org/" +"std/iter/trait.FromIterator.html), which [`HashSet`](https://doc.rust-lang." +"org/std/collections/struct.HashSet.html#impl-FromIterator%3CT%3E-for-" +"HashSet%3CT,+S%3E) implements." msgstr "" #: src/basic-syntax/static-and-const.md:1 @@ -3759,18 +4165,23 @@ msgid "Static and Constant Variables" msgstr "" #: src/basic-syntax/static-and-const.md:3 -msgid "Global state is managed with static and constant variables." +msgid "" +"Static and constant variables are two different ways to create globally-" +"scoped values that cannot be moved or reallocated during the execution of " +"the program. " msgstr "" -#: src/basic-syntax/static-and-const.md:5 +#: src/basic-syntax/static-and-const.md:6 msgid "`const`" msgstr "" -#: src/basic-syntax/static-and-const.md:7 -msgid "You can declare compile-time constants:" +#: src/basic-syntax/static-and-const.md:8 +msgid "" +"Constant variables are evaluated at compile time and their values are " +"inlined wherever they are used:" msgstr "" -#: src/basic-syntax/static-and-const.md:9 +#: src/basic-syntax/static-and-const.md:11 msgid "" "```rust,editable\n" "const DIGEST_SIZE: usize = 3;\n" @@ -3792,21 +4203,29 @@ msgid "" "```" msgstr "" -#: src/basic-syntax/static-and-const.md:27 +#: src/basic-syntax/static-and-const.md:29 msgid "" "According to the [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" "vs-static.html) these are inlined upon use." msgstr "" -#: src/basic-syntax/static-and-const.md:29 -msgid "`static`" -msgstr "" - #: src/basic-syntax/static-and-const.md:31 -msgid "You can also declare static variables:" +msgid "" +"Only functions marked `const` can be called at compile time to generate " +"`const` values. `const` functions can however be called at runtime." msgstr "" #: src/basic-syntax/static-and-const.md:33 +msgid "`static`" +msgstr "" + +#: src/basic-syntax/static-and-const.md:35 +msgid "" +"Static variables will live during the whole execution of the program, and " +"therefore will not move:" +msgstr "" + +#: src/basic-syntax/static-and-const.md:37 msgid "" "```rust,editable\n" "static BANNER: &str = \"Welcome to RustOS 3.14\";\n" @@ -3817,36 +4236,114 @@ msgid "" "```" msgstr "" -#: src/basic-syntax/static-and-const.md:41 +#: src/basic-syntax/static-and-const.md:45 msgid "" "As noted in the [Rust RFC Book](https://rust-lang.github.io/rfcs/0246-const-" "vs-static.html), these are not inlined upon use and have an actual " -"associated memory location. This is useful for unsafe and embedded code, " -"and the variable lives through the entirety of the program execution." -msgstr "" - -#: src/basic-syntax/static-and-const.md:44 -msgid "" -"We will look at mutating static data in the [chapter on Unsafe Rust](../" -"unsafe.md)." -msgstr "" - -#: src/basic-syntax/static-and-const.md:48 -msgid "Mention that `const` behaves semantically similar to C++'s `constexpr`." +"associated memory location. This is useful for unsafe and embedded code, " +"and the variable lives through the entirety of the program execution. When a " +"globally-scoped value does not have a reason to need object identity, " +"`const` is generally preferred." msgstr "" #: src/basic-syntax/static-and-const.md:49 msgid "" +"Because `static` variables are accessible from any thread, they must be " +"`Sync`. Interior mutability is possible through a [`Mutex`](https://doc.rust-" +"lang.org/std/sync/struct.Mutex.html), atomic or similar. It is also possible " +"to have mutable statics, but they require manual synchronisation so any " +"access to them requires `unsafe` code. We will look at [mutable statics](../" +"unsafe/mutable-static-variables.md) in the chapter on Unsafe Rust." +msgstr "" + +#: src/basic-syntax/static-and-const.md:57 +msgid "Mention that `const` behaves semantically similar to C++'s `constexpr`." +msgstr "" + +#: src/basic-syntax/static-and-const.md:58 +msgid "" "`static`, on the other hand, is much more similar to a `const` or mutable " "global variable in C++." msgstr "" -#: src/basic-syntax/static-and-const.md:50 +#: src/basic-syntax/static-and-const.md:59 +msgid "" +"`static` provides object identity: an address in memory and state as " +"required by types with interior mutability such as `Mutex`." +msgstr "" + +#: src/basic-syntax/static-and-const.md:60 msgid "" "It isn't super common that one would need a runtime evaluated constant, but " "it is helpful and safer than using a static." msgstr "" +#: src/basic-syntax/static-and-const.md:61 +msgid "`thread_local` data can be created with the macro `std::thread_local`." +msgstr "" + +#: src/basic-syntax/static-and-const.md:63 +msgid "Properties table:" +msgstr "" + +#: src/basic-syntax/static-and-const.md:65 +msgid "Property" +msgstr "" + +#: src/basic-syntax/static-and-const.md:65 +msgid "Static" +msgstr "" + +#: src/basic-syntax/static-and-const.md:65 +msgid "Constant" +msgstr "" + +#: src/basic-syntax/static-and-const.md:67 +msgid "Has an address in memory" +msgstr "" + +#: src/basic-syntax/static-and-const.md:67 +#: src/basic-syntax/static-and-const.md:68 +#: src/basic-syntax/static-and-const.md:70 +#: src/basic-syntax/static-and-const.md:71 +msgid "Yes" +msgstr "" + +#: src/basic-syntax/static-and-const.md:67 +msgid "No (inlined)" +msgstr "" + +#: src/basic-syntax/static-and-const.md:68 +#, fuzzy +msgid "Lives for the entire duration of the program" +msgstr "`main`関数はプログラムのエントリーポイントになります。" + +#: src/basic-syntax/static-and-const.md:68 +#: src/basic-syntax/static-and-const.md:69 +#: src/basic-syntax/static-and-const.md:71 +msgid "No" +msgstr "" + +#: src/basic-syntax/static-and-const.md:69 +msgid "Can be mutable" +msgstr "" + +#: src/basic-syntax/static-and-const.md:69 +msgid "Yes (unsafe)" +msgstr "" + +#: src/basic-syntax/static-and-const.md:70 +msgid "Evaluated at compile time" +msgstr "" + +#: src/basic-syntax/static-and-const.md:70 +msgid "Yes (initialised at compile time)" +msgstr "" + +#: src/basic-syntax/static-and-const.md:71 +msgid "Inlined wherever it is used" +msgstr "" + #: src/basic-syntax/scopes-shadowing.md:3 msgid "" "You can shadow variables, both those from outer scopes and variables from " @@ -3909,1705 +4406,6 @@ msgid "" "```" msgstr "" -#: src/memory-management.md:3 -msgid "Traditionally, languages have fallen into two broad categories:" -msgstr "" - -#: src/memory-management.md:5 -msgid "Full control via manual memory management: C, C++, Pascal, ..." -msgstr "" - -#: src/memory-management.md:6 -msgid "" -"Full safety via automatic memory management at runtime: Java, Python, Go, " -"Haskell, ..." -msgstr "" - -#: src/memory-management.md:8 -msgid "Rust offers a new mix:" -msgstr "" - -#: src/memory-management.md:10 -msgid "" -"Full control _and_ safety via compile time enforcement of correct memory " -"management." -msgstr "" - -#: src/memory-management.md:13 -msgid "It does this with an explicit ownership concept." -msgstr "" - -#: src/memory-management.md:15 -msgid "First, let's refresh how memory management works." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:1 -msgid "The Stack vs The Heap" -msgstr "" - -#: src/memory-management/stack-vs-heap.md:3 -msgid "Stack: Continuous area of memory for local variables." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:4 -msgid "Values have fixed sizes known at compile time." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:5 -msgid "Extremely fast: just move a stack pointer." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:6 -msgid "Easy to manage: follows function calls." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:7 -msgid "Great memory locality." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:9 -msgid "Heap: Storage of values outside of function calls." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:10 -msgid "Values have dynamic sizes determined at runtime." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:11 -msgid "Slightly slower than the stack: some book-keeping needed." -msgstr "" - -#: src/memory-management/stack-vs-heap.md:12 -msgid "No guarantee of memory locality." -msgstr "" - -#: src/memory-management/stack.md:3 -msgid "" -"Creating a `String` puts fixed-sized data on the stack and dynamically sized " -"data on the heap:" -msgstr "" - -#: src/memory-management/stack.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1 = String::from(\"Hello\");\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/stack.md:12 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" -": | len | 5 | : : +----+----+----+----+----+ :\n" -": | capacity | 5 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/memory-management/stack.md:28 -msgid "" -"Mention that a `String` is backed by a `Vec`, so it has a capacity and " -"length and can grow if mutable via reallocation on the heap." -msgstr "" - -#: src/memory-management/stack.md:30 -msgid "" -"If students ask about it, you can mention that the underlying memory is heap " -"allocated using the [System Allocator](https://doc.rust-lang.org/std/alloc/" -"struct.System.html) and custom allocators can be implemented using the " -"[Allocator API](https://doc.rust-lang.org/std/alloc/index.html)" -msgstr "" - -#: src/memory-management/stack.md:32 -msgid "" -"We can inspect the memory layout with `unsafe` code. However, you should " -"point out that this is rightfully unsafe!" -msgstr "" - -#: src/memory-management/stack.md:34 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut s1 = String::from(\"Hello\");\n" -" s1.push(' ');\n" -" s1.push_str(\"world\");\n" -" // DON'T DO THIS AT HOME! For educational purposes only.\n" -" // String provides no guarantees about its layout, so this could lead " -"to\n" -" // undefined behavior.\n" -" unsafe {\n" -" let (capacity, ptr, len): (usize, usize, usize) = std::mem::" -"transmute(s1);\n" -" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/manual.md:3 -msgid "You allocate and deallocate heap memory yourself." -msgstr "" - -#: src/memory-management/manual.md:5 -msgid "" -"If not done with care, this can lead to crashes, bugs, security " -"vulnerabilities, and memory leaks." -msgstr "" - -#: src/memory-management/manual.md:7 -msgid "C Example" -msgstr "" - -#: src/memory-management/manual.md:9 -msgid "You must call `free` on every pointer you allocate with `malloc`:" -msgstr "" - -#: src/memory-management/manual.md:11 -msgid "" -"```c\n" -"void foo(size_t n) {\n" -" int* int_array = (int*)malloc(n * sizeof(int));\n" -" //\n" -" // ... lots of code\n" -" //\n" -" free(int_array);\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/manual.md:21 -msgid "" -"Memory is leaked if the function returns early between `malloc` and `free`: " -"the pointer is lost and we cannot deallocate the memory." -msgstr "" - -#: src/memory-management/scope-based.md:3 -msgid "" -"Constructors and destructors let you hook into the lifetime of an object." -msgstr "" - -#: src/memory-management/scope-based.md:5 -msgid "" -"By wrapping a pointer in an object, you can free memory when the object is " -"destroyed. The compiler guarantees that this happens, even if an exception " -"is raised." -msgstr "" - -#: src/memory-management/scope-based.md:9 -msgid "" -"This is often called _resource acquisition is initialization_ (RAII) and " -"gives you smart pointers." -msgstr "" - -#: src/memory-management/scope-based.md:12 -msgid "C++ Example" -msgstr "" - -#: src/memory-management/scope-based.md:14 -msgid "" -"```c++\n" -"void say_hello(std::unique_ptr person) {\n" -" std::cout << \"Hello \" << person->name << std::endl;\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/scope-based.md:20 -msgid "" -"The `std::unique_ptr` object is allocated on the stack, and points to memory " -"allocated on the heap." -msgstr "" - -#: src/memory-management/scope-based.md:22 -msgid "At the end of `say_hello`, the `std::unique_ptr` destructor will run." -msgstr "" - -#: src/memory-management/scope-based.md:23 -msgid "The destructor frees the `Person` object it points to." -msgstr "" - -#: src/memory-management/scope-based.md:25 -msgid "" -"Special move constructors are used when passing ownership to a function:" -msgstr "" - -#: src/memory-management/scope-based.md:27 -msgid "" -"```c++\n" -"std::unique_ptr person = find_person(\"Carla\");\n" -"say_hello(std::move(person));\n" -"```" -msgstr "" - -#: src/memory-management/garbage-collection.md:1 -msgid "Automatic Memory Management" -msgstr "" - -#: src/memory-management/garbage-collection.md:3 -msgid "" -"An alternative to manual and scope-based memory management is automatic " -"memory management:" -msgstr "" - -#: src/memory-management/garbage-collection.md:6 -msgid "The programmer never allocates or deallocates memory explicitly." -msgstr "" - -#: src/memory-management/garbage-collection.md:7 -msgid "" -"A garbage collector finds unused memory and deallocates it for the " -"programmer." -msgstr "" - -#: src/memory-management/garbage-collection.md:9 -msgid "Java Example" -msgstr "" - -#: src/memory-management/garbage-collection.md:11 -msgid "The `person` object is not deallocated after `sayHello` returns:" -msgstr "" - -#: src/memory-management/garbage-collection.md:13 -msgid "" -"```java\n" -"void sayHello(Person person) {\n" -" System.out.println(\"Hello \" + person.getName());\n" -"}\n" -"```" -msgstr "" - -#: src/memory-management/rust.md:1 -msgid "Memory Management in Rust" -msgstr "" - -#: src/memory-management/rust.md:3 -msgid "Memory management in Rust is a mix:" -msgstr "" - -#: src/memory-management/rust.md:5 -msgid "Safe and correct like Java, but without a garbage collector." -msgstr "" - -#: src/memory-management/rust.md:6 -msgid "" -"Depending on which abstraction (or combination of abstractions) you choose, " -"can be a single unique pointer, reference counted, or atomically reference " -"counted." -msgstr "" - -#: src/memory-management/rust.md:7 -msgid "Scope-based like C++, but the compiler enforces full adherence." -msgstr "" - -#: src/memory-management/rust.md:8 -msgid "" -"A Rust user can choose the right abstraction for the situation, some even " -"have no cost at runtime like C." -msgstr "" - -#: src/memory-management/rust.md:10 -msgid "It achieves this by modeling _ownership_ explicitly." -msgstr "" - -#: src/memory-management/rust.md:14 -msgid "" -"If asked how at this point, you can mention that in Rust this is usually " -"handled by RAII wrapper types such as [Box](https://doc.rust-lang.org/std/" -"boxed/struct.Box.html), [Vec](https://doc.rust-lang.org/std/vec/struct.Vec." -"html), [Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html), or [Arc]" -"(https://doc.rust-lang.org/std/sync/struct.Arc.html). These encapsulate " -"ownership and memory allocation via various means, and prevent the potential " -"errors in C." -msgstr "" - -#: src/memory-management/rust.md:16 -msgid "" -"You may be asked about destructors here, the [Drop](https://doc.rust-lang." -"org/std/ops/trait.Drop.html) trait is the Rust equivalent." -msgstr "" - -#: src/memory-management/comparison.md:3 -msgid "Here is a rough comparison of the memory management techniques." -msgstr "" - -#: src/memory-management/comparison.md:5 -msgid "Pros of Different Memory Management Techniques" -msgstr "" - -#: src/memory-management/comparison.md:7 src/memory-management/comparison.md:22 -msgid "Manual like C:" -msgstr "" - -#: src/memory-management/comparison.md:8 src/memory-management/comparison.md:14 -#: src/memory-management/comparison.md:17 -msgid "No runtime overhead." -msgstr "" - -#: src/memory-management/comparison.md:9 src/memory-management/comparison.md:26 -msgid "Automatic like Java:" -msgstr "" - -#: src/memory-management/comparison.md:10 -msgid "Fully automatic." -msgstr "" - -#: src/memory-management/comparison.md:11 -#: src/memory-management/comparison.md:18 -msgid "Safe and correct." -msgstr "" - -#: src/memory-management/comparison.md:12 -#: src/memory-management/comparison.md:29 -msgid "Scope-based like C++:" -msgstr "" - -#: src/memory-management/comparison.md:13 -msgid "Partially automatic." -msgstr "" - -#: src/memory-management/comparison.md:15 -msgid "Compiler-enforced scope-based like Rust:" -msgstr "" - -#: src/memory-management/comparison.md:16 -msgid "Enforced by compiler." -msgstr "" - -#: src/memory-management/comparison.md:20 -msgid "Cons of Different Memory Management Techniques" -msgstr "" - -#: src/memory-management/comparison.md:23 -msgid "Use-after-free." -msgstr "" - -#: src/memory-management/comparison.md:24 -msgid "Double-frees." -msgstr "" - -#: src/memory-management/comparison.md:25 -msgid "Memory leaks." -msgstr "" - -#: src/memory-management/comparison.md:27 -msgid "Garbage collection pauses." -msgstr "" - -#: src/memory-management/comparison.md:28 -msgid "Destructor delays." -msgstr "" - -#: src/memory-management/comparison.md:30 -msgid "Complex, opt-in by programmer." -msgstr "" - -#: src/memory-management/comparison.md:31 -msgid "Potential for use-after-free." -msgstr "" - -#: src/memory-management/comparison.md:32 -msgid "Compiler-enforced and scope-based like Rust:" -msgstr "" - -#: src/memory-management/comparison.md:33 -msgid "Some upfront complexity." -msgstr "" - -#: src/memory-management/comparison.md:34 -msgid "Can reject valid programs." -msgstr "" - -#: src/ownership.md:3 -msgid "" -"All variable bindings have a _scope_ where they are valid and it is an error " -"to use a variable outside its scope:" -msgstr "" - -#: src/ownership.md:6 -msgid "" -"```rust,editable,compile_fail\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" {\n" -" let p = Point(3, 4);\n" -" println!(\"x: {}\", p.0);\n" -" }\n" -" println!(\"y: {}\", p.1);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership.md:18 -msgid "" -"At the end of the scope, the variable is _dropped_ and the data is freed." -msgstr "" - -#: src/ownership.md:19 -msgid "A destructor can run here to free up resources." -msgstr "" - -#: src/ownership.md:20 -msgid "We say that the variable _owns_ the value." -msgstr "" - -#: src/ownership/move-semantics.md:3 -msgid "An assignment will transfer ownership between variables:" -msgstr "" - -#: src/ownership/move-semantics.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1: String = String::from(\"Hello!\");\n" -" let s2: String = s1;\n" -" println!(\"s2: {s2}\");\n" -" // println!(\"s1: {s1}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/move-semantics.md:14 -msgid "The assignment of `s1` to `s2` transfers ownership." -msgstr "" - -#: src/ownership/move-semantics.md:15 -msgid "The data was _moved_ from `s1` and `s1` is no longer accessible." -msgstr "" - -#: src/ownership/move-semantics.md:16 -msgid "When `s1` goes out of scope, nothing happens: it has no ownership." -msgstr "" - -#: src/ownership/move-semantics.md:17 -msgid "When `s2` goes out of scope, the string data is freed." -msgstr "" - -#: src/ownership/move-semantics.md:18 -msgid "There is always _exactly_ one variable binding which owns a value." -msgstr "" - -#: src/ownership/move-semantics.md:22 -msgid "" -"Mention that this is the opposite of the defaults in C++, which copies by " -"value unless you use `std::move` (and the move constructor is defined!)." -msgstr "" - -#: src/ownership/move-semantics.md:24 -msgid "In Rust, clones are explicit (by using `clone`)." -msgstr "" - -#: src/ownership/moved-strings-rust.md:3 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let s1: String = String::from(\"Rust\");\n" -" let s2: String = s1;\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/moved-strings-rust.md:10 -msgid "The heap data from `s1` is reused for `s2`." -msgstr "" - -#: src/ownership/moved-strings-rust.md:11 -msgid "When `s1` goes out of scope, nothing happens (it has been moved from)." -msgstr "" - -#: src/ownership/moved-strings-rust.md:13 -msgid "Before move to `s2`:" -msgstr "" - -#: src/ownership/moved-strings-rust.md:15 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+----+ :\n" -": | ptr | o---+---+-----+-->| R | u | s | t | :\n" -": | len | 4 | : : +----+----+----+----+ :\n" -": | capacity | 4 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - - - -'\n" -": :\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/moved-strings-rust.md:30 -msgid "After move to `s2`:" -msgstr "" - -#: src/ownership/moved-strings-rust.md:32 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" -": : : :\n" -": s1 \"(inaccessible)\" : : :\n" -": +-----------+-------+ : : +----+----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" -": | len | 4 | : | : +----+----+----+----+ :\n" -": | capacity | 4 | : | : :\n" -": +-----------+-------+ : | : :\n" -": : | `- - - - - - - - - - - - - -'\n" -": s2 : |\n" -": +-----------+-------+ : |\n" -": | ptr | o---+---+--'\n" -": | len | 4 | :\n" -": | capacity | 4 | :\n" -": +-----------+-------+ :\n" -": :\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:3 -msgid "Modern C++ solves this differently:" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:5 -msgid "" -"```c++\n" -"std::string s1 = \"Cpp\";\n" -"std::string s2 = s1; // Duplicate the data in s1.\n" -"```" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:10 -msgid "" -"The heap data from `s1` is duplicated and `s2` gets its own independent copy." -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:11 -msgid "When `s1` and `s2` go out of scope, they each free their own memory." -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:13 -msgid "Before copy-assignment:" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:16 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:30 -msgid "After copy-assignment:" -msgstr "" - -#: src/ownership/double-free-modern-cpp.md:32 -msgid "" -"```bob\n" -" Stack Heap\n" -".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" -": : : :\n" -": s1 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+--+--+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : : :\n" -": s2 : : :\n" -": +-----------+-------+ : : +----+----+----+ :\n" -": | ptr | o---+---+-----+-->| C | p | p | :\n" -": | len | 3 | : : +----+----+----+ :\n" -": | capacity | 3 | : : :\n" -": +-----------+-------+ : : :\n" -": : `- - - - - - - - - - - -'\n" -"`- - - - - - - - - - - - - -'\n" -"```" -msgstr "" - -#: src/ownership/moves-function-calls.md:3 -msgid "" -"When you pass a value to a function, the value is assigned to the function " -"parameter. This transfers ownership:" -msgstr "" - -#: src/ownership/moves-function-calls.md:6 -msgid "" -"```rust,editable\n" -"fn say_hello(name: String) {\n" -" println!(\"Hello {name}\")\n" -"}\n" -"\n" -"fn main() {\n" -" let name = String::from(\"Alice\");\n" -" say_hello(name);\n" -" // say_hello(name);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/moves-function-calls.md:20 -msgid "" -"With the first call to `say_hello`, `main` gives up ownership of `name`. " -"Afterwards, `name` cannot be used anymore within `main`." -msgstr "" - -#: src/ownership/moves-function-calls.md:21 -msgid "" -"The heap memory allocated for `name` will be freed at the end of the " -"`say_hello` function." -msgstr "" - -#: src/ownership/moves-function-calls.md:22 -msgid "" -"`main` can retain ownership if it passes `name` as a reference (`&name`) and " -"if `say_hello` accepts a reference as a parameter." -msgstr "" - -#: src/ownership/moves-function-calls.md:23 -msgid "" -"Alternatively, `main` can pass a clone of `name` in the first call (`name." -"clone()`)." -msgstr "" - -#: src/ownership/moves-function-calls.md:24 -msgid "" -"Rust makes it harder than C++ to inadvertently create copies by making move " -"semantics the default, and by forcing programmers to make clones explicit." -msgstr "" - -#: src/ownership/copy-clone.md:3 -msgid "" -"While move semantics are the default, certain types are copied by default:" -msgstr "" - -#: src/ownership/copy-clone.md:5 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let x = 42;\n" -" let y = x;\n" -" println!(\"x: {x}\");\n" -" println!(\"y: {y}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/copy-clone.md:14 -msgid "These types implement the `Copy` trait." -msgstr "" - -#: src/ownership/copy-clone.md:16 -msgid "You can opt-in your own types to use copy semantics:" -msgstr "" - -#: src/ownership/copy-clone.md:18 -msgid "" -"```rust,editable\n" -"#[derive(Copy, Clone, Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = p1;\n" -" println!(\"p1: {p1:?}\");\n" -" println!(\"p2: {p2:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/copy-clone.md:30 -msgid "After the assignment, both `p1` and `p2` own their own data." -msgstr "" - -#: src/ownership/copy-clone.md:31 -msgid "We can also use `p1.clone()` to explicitly copy the data." -msgstr "" - -#: src/ownership/copy-clone.md:35 -msgid "Copying and cloning are not the same thing:" -msgstr "" - -#: src/ownership/copy-clone.md:37 -msgid "" -"Copying refers to bitwise copies of memory regions and does not work on " -"arbitrary objects." -msgstr "" - -#: src/ownership/copy-clone.md:38 -msgid "" -"Copying does not allow for custom logic (unlike copy constructors in C++)." -msgstr "" - -#: src/ownership/copy-clone.md:39 -msgid "" -"Cloning is a more general operation and also allows for custom behavior by " -"implementing the `Clone` trait." -msgstr "" - -#: src/ownership/copy-clone.md:40 -msgid "Copying does not work on types that implement the `Drop` trait." -msgstr "" - -#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 -msgid "In the above example, try the following:" -msgstr "" - -#: src/ownership/copy-clone.md:44 -msgid "" -"Add a `String` field to `struct Point`. It will not compile because `String` " -"is not a `Copy` type." -msgstr "" - -#: src/ownership/copy-clone.md:45 -msgid "" -"Remove `Copy` from the `derive` attribute. The compiler error is now in the " -"`println!` for `p1`." -msgstr "" - -#: src/ownership/copy-clone.md:46 -msgid "Show that it works if you clone `p1` instead." -msgstr "" - -#: src/ownership/copy-clone.md:48 -msgid "" -"If students ask about `derive`, it is sufficient to say that this is a way " -"to generate code in Rust at compile time. In this case the default " -"implementations of `Copy` and `Clone` traits are generated." -msgstr "" - -#: src/ownership/borrowing.md:3 -msgid "" -"Instead of transferring ownership when calling a function, you can let a " -"function _borrow_ the value:" -msgstr "" - -#: src/ownership/borrowing.md:6 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn add(p1: &Point, p2: &Point) -> Point {\n" -" Point(p1.0 + p2.0, p1.1 + p2.1)\n" -"}\n" -"\n" -"fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" -" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/borrowing.md:22 -msgid "The `add` function _borrows_ two points and returns a new point." -msgstr "" - -#: src/ownership/borrowing.md:23 -msgid "The caller retains ownership of the inputs." -msgstr "" - -#: src/ownership/borrowing.md:27 -msgid "Notes on stack returns:" -msgstr "" - -#: src/ownership/borrowing.md:28 -msgid "" -"Demonstrate that the return from `add` is cheap because the compiler can " -"eliminate the copy operation. Change the above code to print stack addresses " -"and run it on the [Playground](https://play.rust-lang.org/). In the " -"\"DEBUG\" optimization level, the addresses should change, while they stay " -"the same when changing to the \"RELEASE\" setting:" -msgstr "" - -#: src/ownership/borrowing.md:30 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn add(p1: &Point, p2: &Point) -> Point {\n" -" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" -" println!(\"&p.0: {:p}\", &p.0);\n" -" p\n" -"}\n" -"\n" -"fn main() {\n" -" let p1 = Point(3, 4);\n" -" let p2 = Point(10, 20);\n" -" let p3 = add(&p1, &p2);\n" -" println!(\"&p3.0: {:p}\", &p3.0);\n" -" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/borrowing.md:48 -msgid "The Rust compiler can do return value optimization (RVO)." -msgstr "" - -#: src/ownership/borrowing.md:49 -msgid "" -"In C++, copy elision has to be defined in the language specification because " -"constructors can have side effects. In Rust, this is not an issue at all. If " -"RVO did not happen, Rust will always performs a simple and efficient " -"`memcpy` copy." -msgstr "" - -#: src/ownership/shared-unique-borrows.md:3 -msgid "Rust puts constraints on the ways you can borrow values:" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:5 -msgid "You can have one or more `&T` values at any given time, _or_" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:6 -msgid "You can have exactly one `&mut T` value." -msgstr "" - -#: src/ownership/shared-unique-borrows.md:8 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let mut a: i32 = 10;\n" -" let b: &i32 = &a;\n" -"\n" -" {\n" -" let c: &mut i32 = &mut a;\n" -" *c = 20;\n" -" }\n" -"\n" -" println!(\"a: {a}\");\n" -" println!(\"b: {b}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/shared-unique-borrows.md:25 -msgid "" -"The above code does not compile because `a` is borrowed as mutable (through " -"`c`) and as immutable (through `b`) at the same time." -msgstr "" - -#: src/ownership/shared-unique-borrows.md:26 -msgid "" -"Move the `println!` statement for `b` before the scope that introduces `c` " -"to make the code compile." -msgstr "" - -#: src/ownership/shared-unique-borrows.md:27 -msgid "" -"After that change, the compiler realizes that `b` is only ever used before " -"the new mutable borrow of `a` through `c`. This is a feature of the borrow " -"checker called \"non-lexical lifetimes\"." -msgstr "" - -#: src/ownership/lifetimes.md:3 -msgid "A borrowed value has a _lifetime_:" -msgstr "" - -#: src/ownership/lifetimes.md:5 -msgid "The lifetime can be implicit: `add(p1: &Point, p2: &Point) -> Point`." -msgstr "" - -#: src/ownership/lifetimes.md:6 -msgid "Lifetimes can also be explicit: `&'a Point`, `&'document str`." -msgstr "" - -#: src/ownership/lifetimes.md:7 src/ownership/lifetimes-function-calls.md:23 -msgid "" -"Read `&'a Point` as \"a borrowed `Point` which is valid for at least the " -"lifetime `a`\"." -msgstr "" - -#: src/ownership/lifetimes.md:9 -msgid "" -"Lifetimes are always inferred by the compiler: you cannot assign a lifetime " -"yourself." -msgstr "" - -#: src/ownership/lifetimes.md:11 -msgid "" -"Lifetime annotations create constraints; the compiler verifies that there is " -"a valid solution." -msgstr "" - -#: src/ownership/lifetimes.md:13 -msgid "" -"Lifetimes for function arguments and return values must be fully specified, " -"but Rust allows these to be elidied in most cases with [a few simple rules]" -"(https://doc.rust-lang.org/nomicon/lifetime-elision.html)." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:3 -msgid "" -"In addition to borrowing its arguments, a function can return a borrowed " -"value:" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" -" if p1.0 < p2.0 { p1 } else { p2 }\n" -"}\n" -"\n" -"fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p2: Point = Point(20, 20);\n" -" let p3: &Point = left_most(&p1, &p2);\n" -" println!(\"left-most point: {:?}\", p3);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:21 -msgid "`'a` is a generic parameter, it is inferred by the compiler." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:22 -msgid "Lifetimes start with `'` and `'a` is a typical default name." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:25 -msgid "" -"The _at least_ part is important when parameters are in different scopes." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:31 -msgid "" -"Move the declaration of `p2` and `p3` into a a new scope (`{ ... }`), " -"resulting in the following code:" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:32 -msgid "" -"```rust,ignore\n" -"#[derive(Debug)]\n" -"struct Point(i32, i32);\n" -"\n" -"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" -" if p1.0 < p2.0 { p1 } else { p2 }\n" -"}\n" -"\n" -"fn main() {\n" -" let p1: Point = Point(10, 10);\n" -" let p3: &Point;\n" -" {\n" -" let p2: Point = Point(20, 20);\n" -" p3 = left_most(&p1, &p2);\n" -" }\n" -" println!(\"left-most point: {:?}\", p3);\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:50 -msgid "Note how this does not compile since `p3` outlives `p2`." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:52 -msgid "" -"Reset the workspace and change the function signature to `fn left_most<'a, " -"'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " -"because the relationship between the lifetimes `'a` and `'b` is unclear." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:53 -msgid "Another way to explain it:" -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:54 -msgid "" -"Two references to two values are borrowed by a function and the function " -"returns another reference." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:56 -msgid "" -"It must have come from one of those two inputs (or from a global variable)." -msgstr "" - -#: src/ownership/lifetimes-function-calls.md:57 -msgid "" -"Which one is it? The compiler needs to to know, so at the call site the " -"returned reference is not used for longer than a variable from where the " -"reference came from." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:3 -msgid "" -"If a data type stores borrowed data, it must be annotated with a lifetime:" -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:5 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Highlight<'doc>(&'doc str);\n" -"\n" -"fn erase(text: String) {\n" -" println!(\"Bye {text}!\");\n" -"}\n" -"\n" -"fn main() {\n" -" let text = String::from(\"The quick brown fox jumps over the lazy dog." -"\");\n" -" let fox = Highlight(&text[4..19]);\n" -" let dog = Highlight(&text[35..43]);\n" -" // erase(text);\n" -" println!(\"{fox:?}\");\n" -" println!(\"{dog:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:25 -msgid "" -"In the above example, the annotation on `Highlight` enforces that the data " -"underlying the contained `&str` lives at least as long as any instance of " -"`Highlight` that uses that data." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:26 -msgid "" -"If `text` is consumed before the end of the lifetime of `fox` (or `dog`), " -"the borrow checker throws an error." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:27 -msgid "" -"Types with borrowed data force users to hold on to the original data. This " -"can be useful for creating lightweight views, but it generally makes them " -"somewhat harder to use." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:28 -msgid "When possible, make data structures own their data directly." -msgstr "" - -#: src/ownership/lifetimes-data-structures.md:29 -msgid "" -"Some structs with multiple references inside can have more than one lifetime " -"annotation. This can be necessary if there is a need to describe lifetime " -"relationships between the references themselves, in addition to the lifetime " -"of the struct itself. Those are very advanced use cases." -msgstr "" - -#: src/exercises/day-1/afternoon.md:1 -msgid "Day 1: Afternoon Exercises" -msgstr "" - -#: src/exercises/day-1/afternoon.md:3 -msgid "We will look at two things:" -msgstr "" - -#: src/exercises/day-1/afternoon.md:5 -msgid "A small book library," -msgstr "" - -#: src/exercises/day-1/afternoon.md:7 -msgid "Iterators and ownership (hard)." -msgstr "" - -#: src/exercises/day-1/book-library.md:3 -msgid "" -"We will learn much more about structs and the `Vec` type tomorrow. For " -"now, you just need to know part of its API:" -msgstr "" - -#: src/exercises/day-1/book-library.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut vec = vec![10, 20];\n" -" vec.push(30);\n" -" let midpoint = vec.len() / 2;\n" -" println!(\"middle value: {}\", vec[midpoint]);\n" -" for item in &vec {\n" -" println!(\"item: {item}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/book-library.md:18 -msgid "" -"Use this to create a library application. Copy the code below to and update the types to make it compile:" -msgstr "" - -#: src/exercises/day-1/book-library.md:21 -msgid "" -"```rust,should_panic\n" -"struct Library {\n" -" books: Vec,\n" -"}\n" -"\n" -"struct Book {\n" -" title: String,\n" -" year: u16,\n" -"}\n" -"\n" -"impl Book {\n" -" // This is a constructor, used below.\n" -" fn new(title: &str, year: u16) -> Book {\n" -" Book {\n" -" title: String::from(title),\n" -" year,\n" -" }\n" -" }\n" -"}\n" -"\n" -"// Implement the methods below. Update the `self` parameter to\n" -"// indicate the method's required level of ownership over the object:\n" -"//\n" -"// - `&self` for shared read-only access,\n" -"// - `&mut self` for unique and mutable access,\n" -"// - `self` for unique access by value.\n" -"impl Library {\n" -" fn new() -> Library {\n" -" todo!(\"Initialize and return a `Library` value\")\n" -" }\n" -"\n" -" //fn len(self) -> usize {\n" -" // todo!(\"Return the length of `self.books`\")\n" -" //}\n" -"\n" -" //fn is_empty(self) -> bool {\n" -" // todo!(\"Return `true` if `self.books` is empty\")\n" -" //}\n" -"\n" -" //fn add_book(self, book: Book) {\n" -" // todo!(\"Add a new book to `self.books`\")\n" -" //}\n" -"\n" -" //fn print_books(self) {\n" -" // todo!(\"Iterate over `self.books` and each book's title and " -"year\")\n" -" //}\n" -"\n" -" //fn oldest_book(self) -> Option<&Book> {\n" -" // todo!(\"Return a reference to the oldest book (if any)\")\n" -" //}\n" -"}\n" -"\n" -"// This shows the desired behavior. Uncomment the code below and\n" -"// implement the missing methods. You will need to update the\n" -"// method signatures, including the \"self\" parameter! You may\n" -"// also need to update the variable bindings within main.\n" -"fn main() {\n" -" let library = Library::new();\n" -"\n" -" //println!(\"The library is empty: {}\", library.is_empty());\n" -" //\n" -" //library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" -" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " -"1865));\n" -" //\n" -" //println!(\"The library is no longer empty: {}\", library.is_empty());\n" -" //\n" -" //\n" -" //library.print_books();\n" -" //\n" -" //match library.oldest_book() {\n" -" // Some(book) => println!(\"The oldest book is {}\", book.title),\n" -" // None => println!(\"The library is empty!\"),\n" -" //}\n" -" //\n" -" //println!(\"The library has {} books\", library.len());\n" -" //library.print_books();\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/book-library.md:102 -msgid "[Solution](solutions-afternoon.md#designing-a-library)" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:3 -msgid "" -"The ownership model of Rust affects many APIs. An example of this is the " -"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and " -"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html) " -"traits." -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:8 src/bare-metal/no_std.md:28 -msgid "`Iterator`" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:10 -msgid "" -"Traits are like interfaces: they describe behavior (methods) for a type. The " -"`Iterator` trait simply says that you can call `next` until you get `None` " -"back:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:13 -msgid "" -"```rust\n" -"pub trait Iterator {\n" -" type Item;\n" -" fn next(&mut self) -> Option;\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:20 -msgid "You use this trait like this:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:22 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();\n" -"\n" -" println!(\"v[0]: {:?}\", iter.next());\n" -" println!(\"v[1]: {:?}\", iter.next());\n" -" println!(\"v[2]: {:?}\", iter.next());\n" -" println!(\"No more items: {:?}\", iter.next());\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:34 -msgid "What is the type returned by the iterator? Test your answer here:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:36 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let v: Vec = vec![10, 20, 30];\n" -" let mut iter = v.iter();\n" -"\n" -" let v0: Option<..> = iter.next();\n" -" println!(\"v0: {v0:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:46 -msgid "Why is this type used?" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:48 -msgid "`IntoIterator`" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:50 -msgid "" -"The `Iterator` trait tells you how to _iterate_ once you have created an " -"iterator. The related trait `IntoIterator` tells you how to create the " -"iterator:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:53 -msgid "" -"```rust\n" -"pub trait IntoIterator {\n" -" type Item;\n" -" type IntoIter: Iterator;\n" -"\n" -" fn into_iter(self) -> Self::IntoIter;\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:62 -msgid "" -"The syntax here means that every implementation of `IntoIterator` must " -"declare two types:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:65 -msgid "`Item`: the type we iterate over, such as `i8`," -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:66 -msgid "`IntoIter`: the `Iterator` type returned by the `into_iter` method." -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:68 -msgid "" -"Note that `IntoIter` and `Item` are linked: the iterator must have the same " -"`Item` type, which means that it returns `Option`" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:71 -msgid "Like before, what is the type returned by the iterator?" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:73 -msgid "" -"```rust,editable,compile_fail\n" -"fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::" -"from(\"bar\")];\n" -" let mut iter = v.into_iter();\n" -"\n" -" let v0: Option<..> = iter.next();\n" -" println!(\"v0: {v0:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:83 -msgid "`for` Loops" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:85 -msgid "" -"Now that we know both `Iterator` and `IntoIterator`, we can build `for` " -"loops. They call `into_iter()` on an expression and iterates over the " -"resulting iterator:" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:89 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v: Vec = vec![String::from(\"foo\"), String::" -"from(\"bar\")];\n" -"\n" -" for word in &v {\n" -" println!(\"word: {word}\");\n" -" }\n" -"\n" -" for word in v {\n" -" println!(\"word: {word}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:103 -msgid "What is the type of `word` in each loop?" -msgstr "" - -#: src/exercises/day-1/iterators-and-ownership.md:105 -msgid "" -"Experiment with the code above and then consult the documentation for [`impl " -"IntoIterator for &Vec`](https://doc.rust-lang.org/std/vec/struct.Vec." -"html#impl-IntoIterator-for-%26%27a%20Vec%3CT%2C%20A%3E) and [`impl " -"IntoIterator for Vec`](https://doc.rust-lang.org/std/vec/struct.Vec." -"html#impl-IntoIterator-for-Vec%3CT%2C%20A%3E) to check your answers." -msgstr "" - -#: src/welcome-day-2.md:1 -msgid "Welcome to Day 2" -msgstr "" - -#: src/welcome-day-2.md:3 -msgid "Now that we have seen a fair amount of Rust, we will continue with:" -msgstr "" - -#: src/welcome-day-2.md:5 -msgid "Structs, enums, methods." -msgstr "" - -#: src/welcome-day-2.md:7 -msgid "Pattern matching: destructuring enums, structs, and arrays." -msgstr "" - -#: src/welcome-day-2.md:9 -msgid "" -"Control flow constructs: `if`, `if let`, `while`, `while let`, `break`, and " -"`continue`." -msgstr "" - -#: src/welcome-day-2.md:12 -msgid "" -"The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, " -"`Rc` and `Arc`." -msgstr "" - -#: src/welcome-day-2.md:15 -msgid "Modules: visibility, paths, and filesystem hierarchy." -msgstr "" - -#: src/structs.md:3 -msgid "Like C and C++, Rust has support for custom structs:" -msgstr "" - -#: src/structs.md:5 -msgid "" -"```rust,editable\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"fn main() {\n" -" let mut peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" -" };\n" -" println!(\"{} is {} years old\", peter.name, peter.age);\n" -" \n" -" peter.age = 28;\n" -" println!(\"{} is {} years old\", peter.name, peter.age);\n" -" \n" -" let jackie = Person {\n" -" name: String::from(\"Jackie\"),\n" -" ..peter\n" -" };\n" -" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" -"}\n" -"```" -msgstr "" - -#: src/structs.md:31 src/enums.md:33 src/enums/sizes.md:29 src/methods.md:30 -#: src/methods/example.md:46 src/pattern-matching.md:25 -#: src/pattern-matching/match-guards.md:22 src/control-flow/blocks.md:42 -msgid "Key Points:" -msgstr "" - -#: src/structs.md:33 -msgid "Structs work like in C or C++." -msgstr "" - -#: src/structs.md:34 -msgid "Like in C++, and unlike in C, no typedef is needed to define a type." -msgstr "" - -#: src/structs.md:35 -msgid "Unlike in C++, there is no inheritance between structs." -msgstr "" - -#: src/structs.md:36 -msgid "" -"Methods are defined in an `impl` block, which we will see in following " -"slides." -msgstr "" - -#: src/structs.md:37 -msgid "" -"This may be a good time to let people know there are different types of " -"structs. " -msgstr "" - -#: src/structs.md:38 -msgid "" -"Zero-sized structs `e.g., struct Foo;` might be used when implementing a " -"trait on some type but don’t have any data that you want to store in the " -"value itself. " -msgstr "" - -#: src/structs.md:39 -msgid "" -"The next slide will introduce Tuple structs, used when the field names are " -"not important." -msgstr "" - -#: src/structs.md:40 -msgid "" -"The syntax `..peter` allows us to copy the majority of the fields from the " -"old struct without having to explicitly type it all out. It must always be " -"the last element." -msgstr "" - -#: src/structs/tuple-structs.md:3 -msgid "If the field names are unimportant, you can use a tuple struct:" -msgstr "" - -#: src/structs/tuple-structs.md:5 -msgid "" -"```rust,editable\n" -"struct Point(i32, i32);\n" -"\n" -"fn main() {\n" -" let p = Point(17, 23);\n" -" println!(\"({}, {})\", p.0, p.1);\n" -"}\n" -"```" -msgstr "" - -#: src/structs/tuple-structs.md:14 -msgid "This is often used for single-field wrappers (called newtypes):" -msgstr "" - -#: src/structs/tuple-structs.md:16 -msgid "" -"```rust,editable,compile_fail\n" -"struct PoundsOfForce(f64);\n" -"struct Newtons(f64);\n" -"\n" -"fn compute_thruster_force() -> PoundsOfForce {\n" -" todo!(\"Ask a rocket scientist at NASA\")\n" -"}\n" -"\n" -"fn set_thruster_force(force: Newtons) {\n" -" // ...\n" -"}\n" -"\n" -"fn main() {\n" -" let force = compute_thruster_force();\n" -" set_thruster_force(force);\n" -"}\n" -"\n" -"```" -msgstr "" - -#: src/structs/tuple-structs.md:37 -msgid "" -"Newtypes are a great way to encode additional information about the value in " -"a primitive type, for example:" -msgstr "" - -#: src/structs/tuple-structs.md:38 -msgid "The number is measured in some units: `Newtons` in the example above." -msgstr "" - -#: src/structs/tuple-structs.md:39 -msgid "" -"The value passed some validation when it was created, so you no longer have " -"to validate it again at every use: 'PhoneNumber(String)`or`OddNumber(u32)\\`." -msgstr "" - -#: src/structs/tuple-structs.md:40 -msgid "" -"Demonstrate how to add a `f64` value to a `Newtons` type by accessing the " -"single field in the newtype." -msgstr "" - -#: src/structs/tuple-structs.md:41 -msgid "" -"Rust generally doesn’t like inexplicit things, like automatic unwrapping or " -"for instance using booleans as integers." -msgstr "" - -#: src/structs/tuple-structs.md:42 -msgid "Operator overloading is discussed on Day 3 (generics). " -msgstr "" - -#: src/structs/field-shorthand.md:3 -msgid "" -"If you already have variables with the right names, then you can create the " -"struct using a shorthand:" -msgstr "" - -#: src/structs/field-shorthand.md:6 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Person {\n" -" Person { name, age }\n" -" }\n" -"}\n" -"\n" -"fn main() {\n" -" let peter = Person::new(String::from(\"Peter\"), 27);\n" -" println!(\"{peter:?}\");\n" -"}\n" -"```" -msgstr "" - -#: src/structs/field-shorthand.md:27 -msgid "" -"The `new` function could be written using `Self` as a type, as it is " -"interchangeable with the struct type name" -msgstr "" - -#: src/structs/field-shorthand.md:29 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"impl Person {\n" -" fn new(name: String, age: u8) -> Self {\n" -" Self { name, age }\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/structs/field-shorthand.md:41 -msgid "" -"Implement the `Default` trait for the struct. Define some fields and use the " -"default values for the other fields." -msgstr "" - -#: src/structs/field-shorthand.md:43 -msgid "" -"```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"impl Default for Person {\n" -" fn default() -> Person {\n" -" Person {\n" -" name: \"Bot\".to_string(),\n" -" age: 0,\n" -" }\n" -" }\n" -"}\n" -"fn create_default() {\n" -" let tmp = Person {\n" -" ..Default::default()\n" -" };\n" -" let tmp = Person {\n" -" name: \"Sam\".to_string(),\n" -" ..Default::default()\n" -" };\n" -"}\n" -"```" -msgstr "" - -#: src/structs/field-shorthand.md:68 -msgid "Methods are defined in the `impl` block." -msgstr "" - -#: src/structs/field-shorthand.md:69 -msgid "" -"Use struct update syntax to define a new structure using `peter`. Note that " -"the variable `peter` will no longer be accessible afterwards." -msgstr "" - -#: src/structs/field-shorthand.md:70 -msgid "" -"Use `{:#?}` when printing structs to request the `Debug` representation." -msgstr "" - #: src/enums.md:3 msgid "" "The `enum` keyword allows the creation of a type which has a few different " @@ -5618,6 +4416,7 @@ msgstr "" msgid "" "```rust,editable\n" "fn generate_random_number() -> i32 {\n" +" // Implementation based on https://xkcd.com/221/\n" " 4 // Chosen by fair dice roll. Guaranteed to be random.\n" "}\n" "\n" @@ -5642,31 +4441,31 @@ msgid "" "```" msgstr "" -#: src/enums.md:35 +#: src/enums.md:36 msgid "Enumerations allow you to collect a set of values under one type" msgstr "" -#: src/enums.md:36 +#: src/enums.md:37 msgid "" "This page offers an enum type `CoinFlip` with two variants `Heads` and " -"`Tail`. You might note the namespace when using variants." -msgstr "" - -#: src/enums.md:37 -msgid "This might be a good time to compare Structs and Enums:" +"`Tails`. You might note the namespace when using variants." msgstr "" #: src/enums.md:38 +msgid "This might be a good time to compare Structs and Enums:" +msgstr "" + +#: src/enums.md:39 msgid "" "In both, you can have a simple version without fields (unit struct) or one " "with different types of fields (variant payloads). " msgstr "" -#: src/enums.md:39 +#: src/enums.md:40 msgid "In both, associated functions are defined within an `impl` block." msgstr "" -#: src/enums.md:40 +#: src/enums.md:41 msgid "" "You could even implement the different variants of an enum with separate " "structs but then they wouldn’t be the same type as they would if they were " @@ -5772,13 +4571,12 @@ msgstr "" #: src/enums/sizes.md:5 msgid "" "```rust,editable\n" +"use std::any::type_name;\n" "use std::mem::{align_of, size_of};\n" "\n" -"macro_rules! dbg_size {\n" -" ($t:ty) => {\n" -" println!(\"{}: size {} bytes, align: {} bytes\",\n" -" stringify!($t), size_of::<$t>(), align_of::<$t>());\n" -" };\n" +"fn dbg_size() {\n" +" println!(\"{}: size {} bytes, align: {} bytes\",\n" +" type_name::(), size_of::(), align_of::());\n" "}\n" "\n" "enum Foo {\n" @@ -5787,29 +4585,29 @@ msgid "" "}\n" "\n" "fn main() {\n" -" dbg_size!(Foo);\n" +" dbg_size::();\n" "}\n" "```" msgstr "" -#: src/enums/sizes.md:25 +#: src/enums/sizes.md:24 msgid "" "See the [Rust Reference](https://doc.rust-lang.org/reference/type-layout." "html)." msgstr "" -#: src/enums/sizes.md:31 +#: src/enums/sizes.md:30 msgid "" "Internally Rust is using a field (discriminant) to keep track of the enum " "variant." msgstr "" -#: src/enums/sizes.md:33 +#: src/enums/sizes.md:32 msgid "" "You can control the discriminant if needed (e.g., for compatibility with C):" msgstr "" -#: src/enums/sizes.md:35 +#: src/enums/sizes.md:34 msgid "" "```rust,editable\n" "#[repr(u32)]\n" @@ -5827,57 +4625,57 @@ msgid "" "```" msgstr "" -#: src/enums/sizes.md:50 +#: src/enums/sizes.md:49 msgid "" "Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2 " "bytes." msgstr "" -#: src/enums/sizes.md:54 +#: src/enums/sizes.md:53 msgid "Try out other types such as" msgstr "" -#: src/enums/sizes.md:56 +#: src/enums/sizes.md:55 msgid "`dbg_size!(bool)`: size 1 bytes, align: 1 bytes," msgstr "" -#: src/enums/sizes.md:57 +#: src/enums/sizes.md:56 msgid "" "`dbg_size!(Option)`: size 1 bytes, align: 1 bytes (niche optimization, " "see below)," msgstr "" -#: src/enums/sizes.md:58 +#: src/enums/sizes.md:57 msgid "`dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine)," msgstr "" -#: src/enums/sizes.md:59 +#: src/enums/sizes.md:58 msgid "" "`dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer " "optimization, see below)." msgstr "" -#: src/enums/sizes.md:61 +#: src/enums/sizes.md:60 msgid "" -"Niche optimization: Rust will merge use unused bit patterns for the enum " +"Niche optimization: Rust will merge unused bit patterns for the enum " "discriminant." msgstr "" -#: src/enums/sizes.md:64 +#: src/enums/sizes.md:63 msgid "" "Null pointer optimization: For [some types](https://doc.rust-lang.org/std/" "option/#representation), Rust guarantees that `size_of::()` equals " "`size_of::>()`." msgstr "" -#: src/enums/sizes.md:68 +#: src/enums/sizes.md:67 msgid "" "Example code if you want to show how the bitwise representation _may_ look " "like in practice. It's important to note that the compiler provides no " "guarantees regarding this representation, therefore this is totally unsafe." msgstr "" -#: src/enums/sizes.md:71 +#: src/enums/sizes.md:70 msgid "" "```rust,editable\n" "use std::mem::transmute;\n" @@ -5916,13 +4714,13 @@ msgid "" "```" msgstr "" -#: src/enums/sizes.md:106 +#: src/enums/sizes.md:105 msgid "" "More complex example if you want to discuss what happens when we chain more " "than 256 `Option`s together." msgstr "" -#: src/enums/sizes.md:108 +#: src/enums/sizes.md:107 msgid "" "```rust,editable\n" "#![recursion_limit = \"1000\"]\n" @@ -5975,210 +4773,193 @@ msgid "" "```" msgstr "" -#: src/methods.md:3 +#: src/control-flow/novel.md:3 msgid "" -"Rust allows you to associate functions with your new types. You do this with " -"an `impl` block:" +"Rust has a few control flow constructs which differ from other languages. " +"They are used for pattern matching:" msgstr "" -#: src/methods.md:6 +#: src/control-flow/novel.md:6 src/control-flow/if-let-expressions.md:1 +msgid "`if let` expressions" +msgstr "" + +#: src/control-flow/novel.md:7 +#, fuzzy +msgid "`while let` expressions" +msgstr "while let式" + +#: src/control-flow/novel.md:8 src/control-flow/match-expressions.md:1 +msgid "`match` expressions" +msgstr "" + +#: src/control-flow/if-let-expressions.md:3 +msgid "" +"The [`if let` expression](https://doc.rust-lang.org/reference/expressions/if-" +"expr.html#if-let-expressions) lets you execute different code depending on " +"whether a value matches a pattern:" +msgstr "" + +#: src/control-flow/if-let-expressions.md:7 msgid "" "```rust,editable\n" -"#[derive(Debug)]\n" -"struct Person {\n" -" name: String,\n" -" age: u8,\n" -"}\n" -"\n" -"impl Person {\n" -" fn say_hello(&self) {\n" -" println!(\"Hello, my name is {}\", self.name);\n" +"fn main() {\n" +" let arg = std::env::args().next();\n" +" if let Some(value) = arg {\n" +" println!(\"Program name: {value}\");\n" +" } else {\n" +" println!(\"Missing name?\");\n" " }\n" "}\n" -"\n" +"```" +msgstr "" + +#: src/control-flow/if-let-expressions.md:18 +#: src/control-flow/while-let-expressions.md:21 +#: src/control-flow/match-expressions.md:23 +msgid "" +"See [pattern matching](../pattern-matching.md) for more details on patterns " +"in Rust." +msgstr "" + +#: src/control-flow/if-let-expressions.md:23 +msgid "" +"Unlike `match`, `if let` does not have to cover all branches. This can make " +"it more concise than `match`." +msgstr "" + +#: src/control-flow/if-let-expressions.md:24 +msgid "A common usage is handling `Some` values when working with `Option`." +msgstr "" + +#: src/control-flow/if-let-expressions.md:25 +msgid "" +"Unlike `match`, `if let` does not support guard clauses for pattern matching." +msgstr "" + +#: src/control-flow/if-let-expressions.md:26 +msgid "" +"Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/" +"flow_control/let_else.html) construct allows to do a destructuring " +"assignment, or if it fails, execute a block which is required to abort " +"normal control flow (with `panic`/`return`/`break`/`continue`):" +msgstr "" + +#: src/control-flow/if-let-expressions.md:28 +msgid "" +"```rust,editable\n" "fn main() {\n" -" let peter = Person {\n" -" name: String::from(\"Peter\"),\n" -" age: 27,\n" +" println!(\"{:?}\", second_word_to_upper(\"foo bar\"));\n" +"}\n" +" \n" +"fn second_word_to_upper(s: &str) -> Option {\n" +" let mut it = s.split(' ');\n" +" let (Some(_), Some(item)) = (it.next(), it.next()) else {\n" +" return None;\n" " };\n" -" peter.say_hello();\n" +" Some(item.to_uppercase())\n" "}\n" +"\n" "```" msgstr "" -#: src/methods.md:31 -msgid "It can be helpful to introduce methods by comparing them to functions." +#: src/control-flow/while-let-expressions.md:1 +msgid "`while let` loops" msgstr "" -#: src/methods.md:32 +#: src/control-flow/while-let-expressions.md:3 msgid "" -"Methods are called on an instance of a type (such as a struct or enum), the " -"first parameter represents the instance as `self`." +"Like with `if let`, there is a [`while let`](https://doc.rust-lang.org/" +"reference/expressions/loop-expr.html#predicate-pattern-loops) variant which " +"repeatedly tests a value against a pattern:" msgstr "" -#: src/methods.md:33 -msgid "" -"Developers may choose to use methods to take advantage of method receiver " -"syntax and to help keep them more organized. By using methods we can keep " -"all the implementation code in one predictable place." -msgstr "" - -#: src/methods.md:34 -msgid "Point out the use of the keyword `self`, a method receiver. " -msgstr "" - -#: src/methods.md:35 -msgid "" -"Show that it is an abbreviated term for `self:&Self` and perhaps show how " -"the struct name could also be used. " -msgstr "" - -#: src/methods.md:36 -msgid "" -"Explain that `Self` is a type alias for the type the `impl` block is in and " -"can be used elsewhere in the block." -msgstr "" - -#: src/methods.md:37 -msgid "" -"Note how `self` is used like other structs and dot notation can be used to " -"refer to individual fields." -msgstr "" - -#: src/methods.md:38 -msgid "" -"This might be a good time to demonstrate how the `&self` differs from `self` " -"by modifying the code and trying to run say_hello twice." -msgstr "" - -#: src/methods.md:39 -msgid "We describe the distinction between method receivers next." -msgstr "" - -#: src/methods/receiver.md:3 -msgid "" -"The `&self` above indicates that the method borrows the object immutably. " -"There are other possible receivers for a method:" -msgstr "" - -#: src/methods/receiver.md:6 -msgid "" -"`&self`: borrows the object from the caller using a shared and immutable " -"reference. The object can be used again afterwards." -msgstr "" - -#: src/methods/receiver.md:8 -msgid "" -"`&mut self`: borrows the object from the caller using a unique and mutable " -"reference. The object can be used again afterwards." -msgstr "" - -#: src/methods/receiver.md:10 -msgid "" -"`self`: takes ownership of the object and moves it away from the caller. The " -"method becomes the owner of the object. The object will be dropped " -"(deallocated) when the method returns, unless its ownership is explicitly " -"transmitted. Complete ownership does not automatically mean mutability." -msgstr "" - -#: src/methods/receiver.md:14 -msgid "`mut self`: same as above, but the method can mutate the object. " -msgstr "" - -#: src/methods/receiver.md:15 -msgid "" -"No receiver: this becomes a static method on the struct. Typically used to " -"create constructors which are called `new` by convention." -msgstr "" - -#: src/methods/receiver.md:18 -msgid "" -"Beyond variants on `self`, there are also [special wrapper types](https://" -"doc.rust-lang.org/reference/special-types-and-traits.html) allowed to be " -"receiver types, such as `Box`." -msgstr "" - -#: src/methods/receiver.md:24 -msgid "" -"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". " -"These constraints always come together in Rust due to borrow checker rules, " -"and `self` is no exception. It isn't possible to reference a struct from " -"multiple locations and call a mutating (`&mut self`) method on it." -msgstr "" - -#: src/methods/example.md:3 +#: src/control-flow/while-let-expressions.md:6 msgid "" "```rust,editable\n" -"#[derive(Debug)]\n" -"struct Race {\n" -" name: String,\n" -" laps: Vec,\n" -"}\n" -"\n" -"impl Race {\n" -" fn new(name: &str) -> Race { // No receiver, a static method\n" -" Race { name: String::from(name), laps: Vec::new() }\n" -" }\n" -"\n" -" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write " -"access to self\n" -" self.laps.push(lap);\n" -" }\n" -"\n" -" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" -" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" -" for (idx, lap) in self.laps.iter().enumerate() {\n" -" println!(\"Lap {idx}: {lap} sec\");\n" -" }\n" -" }\n" -"\n" -" fn finish(self) { // Exclusive ownership of self\n" -" let total = self.laps.iter().sum::();\n" -" println!(\"Race {} is finished, total lap time: {}\", self.name, " -"total);\n" -" }\n" -"}\n" -"\n" "fn main() {\n" -" let mut race = Race::new(\"Monaco Grand Prix\");\n" -" race.add_lap(70);\n" -" race.add_lap(68);\n" -" race.print_laps();\n" -" race.add_lap(71);\n" -" race.print_laps();\n" -" race.finish();\n" -" // race.add_lap(42);\n" +" let v = vec![10, 20, 30];\n" +" let mut iter = v.into_iter();\n" +"\n" +" while let Some(x) = iter.next() {\n" +" println!(\"x: {x}\");\n" +" }\n" "}\n" "```" msgstr "" -#: src/methods/example.md:47 -msgid "All four methods here use a different method receiver." +#: src/control-flow/while-let-expressions.md:17 +msgid "" +"Here the iterator returned by `v.into_iter()` will return a `Option` on " +"every call to `next()`. It returns `Some(x)` until it is done, after which " +"it will return `None`. The `while let` lets us keep iterating through all " +"items." msgstr "" -#: src/methods/example.md:48 +#: src/control-flow/while-let-expressions.md:26 msgid "" -"You can point out how that changes what the function can do with the " -"variable values and if/how it can be used again in `main`." +"Point out that the `while let` loop will keep going as long as the value " +"matches the pattern." msgstr "" -#: src/methods/example.md:49 +#: src/control-flow/while-let-expressions.md:27 msgid "" -"You can showcase the error that appears when trying to call `finish` twice." +"You could rewrite the `while let` loop as an infinite loop with an if " +"statement that breaks when there is no value to unwrap for `iter.next()`. " +"The `while let` provides syntactic sugar for the above scenario." msgstr "" -#: src/methods/example.md:50 +#: src/control-flow/match-expressions.md:3 msgid "" -"Note that although the method receivers are different, the non-static " -"functions are called the same way in the main body. Rust enables automatic " -"referencing and dereferencing when calling methods. Rust automatically adds " -"in the `&`, `*`, `muts` so that that object matches the method signature." +"The [`match` keyword](https://doc.rust-lang.org/reference/expressions/match-" +"expr.html) is used to match a value against one or more patterns. In that " +"sense, it works like a series of `if let` expressions:" msgstr "" -#: src/methods/example.md:51 +#: src/control-flow/match-expressions.md:7 msgid "" -"You might point out that `print_laps` is using a vector that is iterated " -"over. We describe vectors in more detail in the afternoon. " +"```rust,editable\n" +"fn main() {\n" +" match std::env::args().next().as_deref() {\n" +" Some(\"cat\") => println!(\"Will do cat things\"),\n" +" Some(\"ls\") => println!(\"Will ls some files\"),\n" +" Some(\"mv\") => println!(\"Let's move some files\"),\n" +" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" +" None => println!(\"Hmm, no program name?\"),\n" +" _ => println!(\"Unknown program name!\"),\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/control-flow/match-expressions.md:20 +msgid "" +"Like `if let`, each match arm must have the same type. The type is the last " +"expression of the block, if any. In the example above, the type is `()`." +msgstr "" + +#: src/control-flow/match-expressions.md:28 +msgid "Save the match expression to a variable and print it out." +msgstr "" + +#: src/control-flow/match-expressions.md:29 +msgid "Remove `.as_deref()` and explain the error." +msgstr "" + +#: src/control-flow/match-expressions.md:30 +msgid "" +"`std::env::args().next()` returns an `Option`, but we cannot match " +"against `String`." +msgstr "" + +#: src/control-flow/match-expressions.md:31 +msgid "" +"`as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, " +"this turns `Option` into `Option<&str>`." +msgstr "" + +#: src/control-flow/match-expressions.md:32 +msgid "" +"We can now use pattern matching to match against the `&str` inside `Option`." msgstr "" #: src/pattern-matching.md:3 @@ -6455,6 +5236,1298 @@ msgid "" "with an `|`." msgstr "" +#: src/exercises/day-1/afternoon.md:1 +msgid "Day 1: Afternoon Exercises" +msgstr "" + +#: src/exercises/day-1/afternoon.md:3 +msgid "We will look at two things:" +msgstr "" + +#: src/exercises/day-1/afternoon.md:5 +#, fuzzy +msgid "The Luhn algorithm," +msgstr "Luhnアルゴリズム" + +#: src/exercises/day-1/afternoon.md:7 +#, fuzzy +msgid "An exercise on pattern matching." +msgstr "列挙型とパターンマッチング" + +#: src/exercises/day-1/afternoon.md:11 src/exercises/day-2/afternoon.md:7 +#: src/exercises/bare-metal/afternoon.md:7 +#: src/exercises/concurrency/afternoon.md:13 +msgid "" +"After looking at the exercises, you can look at the [solutions](solutions-" +"afternoon.md) provided." +msgstr "" + +#: src/exercises/day-1/luhn.md:3 +msgid "" +"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used " +"to validate credit card numbers. The algorithm takes a string as input and " +"does the following to validate the credit card number:" +msgstr "" + +#: src/exercises/day-1/luhn.md:7 +msgid "Ignore all spaces. Reject number with less than two digits." +msgstr "" + +#: src/exercises/day-1/luhn.md:9 +msgid "" +"Moving from **right to left**, double every second digit: for the number " +"`1234`, we double `3` and `1`. For the number `98765`, we double `6` and `8`." +msgstr "" + +#: src/exercises/day-1/luhn.md:12 +msgid "" +"After doubling a digit, sum the digits. So doubling `7` becomes `14` which " +"becomes `5`." +msgstr "" + +#: src/exercises/day-1/luhn.md:15 +msgid "Sum all the undoubled and doubled digits." +msgstr "" + +#: src/exercises/day-1/luhn.md:17 +msgid "The credit card number is valid if the sum ends with `0`." +msgstr "" + +#: src/exercises/day-1/luhn.md:19 +msgid "" +"Copy the code below to and implement the " +"function." +msgstr "" + +#: src/exercises/day-1/luhn.md:21 +msgid "" +"Try to solve the problem the \"simple\" way first, using `for` loops and " +"integers. Then, revisit the solution and try to implement it with iterators." +msgstr "" + +#: src/exercises/day-1/luhn.md:25 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" unimplemented!()\n" +"}\n" +"\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/welcome-day-2.md:1 +msgid "Welcome to Day 2" +msgstr "" + +#: src/welcome-day-2.md:3 +msgid "Now that we have seen a fair amount of Rust, we will continue with:" +msgstr "" + +#: src/welcome-day-2.md:5 +msgid "" +"Memory management: stack vs heap, manual memory management, scope-based " +"memory management, and garbage collection." +msgstr "" +"メモリ管理: スタック vs ヒープ、手動でのメモリ管理、スコープに基づくメモリ管" +"理、ガベージコレクション。" + +#: src/welcome-day-2.md:8 +msgid "" +"Ownership: move semantics, copying and cloning, borrowing, and lifetimes." +msgstr "所有権: ムーブセマンティクス、コピーとクローン、借用、ライフタイム。" + +#: src/welcome-day-2.md:10 +#, fuzzy +msgid "Structs and methods." +msgstr "文字列とイテレータ" + +#: src/welcome-day-2.md:12 +msgid "" +"The Standard Library: `String`, `Option` and `Result`, `Vec`, `HashMap`, " +"`Rc` and `Arc`." +msgstr "" + +#: src/welcome-day-2.md:15 +msgid "Modules: visibility, paths, and filesystem hierarchy." +msgstr "" + +#: src/memory-management.md:3 +msgid "Traditionally, languages have fallen into two broad categories:" +msgstr "" + +#: src/memory-management.md:5 +msgid "Full control via manual memory management: C, C++, Pascal, ..." +msgstr "" + +#: src/memory-management.md:6 +msgid "" +"Full safety via automatic memory management at runtime: Java, Python, Go, " +"Haskell, ..." +msgstr "" + +#: src/memory-management.md:8 +msgid "Rust offers a new mix:" +msgstr "" + +#: src/memory-management.md:10 +msgid "" +"Full control _and_ safety via compile time enforcement of correct memory " +"management." +msgstr "" + +#: src/memory-management.md:13 +msgid "It does this with an explicit ownership concept." +msgstr "" + +#: src/memory-management.md:15 +msgid "First, let's refresh how memory management works." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:1 +msgid "The Stack vs The Heap" +msgstr "" + +#: src/memory-management/stack-vs-heap.md:3 +msgid "Stack: Continuous area of memory for local variables." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:4 +msgid "Values have fixed sizes known at compile time." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:5 +msgid "Extremely fast: just move a stack pointer." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:6 +msgid "Easy to manage: follows function calls." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:7 +msgid "Great memory locality." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:9 +msgid "Heap: Storage of values outside of function calls." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:10 +msgid "Values have dynamic sizes determined at runtime." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:11 +msgid "Slightly slower than the stack: some book-keeping needed." +msgstr "" + +#: src/memory-management/stack-vs-heap.md:12 +msgid "No guarantee of memory locality." +msgstr "" + +#: src/memory-management/stack.md:1 +#, fuzzy +msgid "Stack and Heap Example" +msgstr "スタック vs ヒープ" + +#: src/memory-management/stack.md:3 +msgid "" +"Creating a `String` puts fixed-sized metadata on the stack and dynamically " +"sized data, the actual string, on the heap:" +msgstr "" + +#: src/memory-management/stack.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1 = String::from(\"Hello\");\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:12 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| H | e | l | l | o | :\n" +": | len | 5 | : : +----+----+----+----+----+ :\n" +": | capacity | 5 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/memory-management/stack.md:28 +msgid "" +"Mention that a `String` is backed by a `Vec`, so it has a capacity and " +"length and can grow if mutable via reallocation on the heap." +msgstr "" + +#: src/memory-management/stack.md:30 +msgid "" +"If students ask about it, you can mention that the underlying memory is heap " +"allocated using the [System Allocator](https://doc.rust-lang.org/std/alloc/" +"struct.System.html) and custom allocators can be implemented using the " +"[Allocator API](https://doc.rust-lang.org/std/alloc/index.html)" +msgstr "" + +#: src/memory-management/stack.md:32 +msgid "" +"We can inspect the memory layout with `unsafe` code. However, you should " +"point out that this is rightfully unsafe!" +msgstr "" + +#: src/memory-management/stack.md:34 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut s1 = String::from(\"Hello\");\n" +" s1.push(' ');\n" +" s1.push_str(\"world\");\n" +" // DON'T DO THIS AT HOME! For educational purposes only.\n" +" // String provides no guarantees about its layout, so this could lead " +"to\n" +" // undefined behavior.\n" +" unsafe {\n" +" let (ptr, capacity, len): (usize, usize, usize) = std::mem::" +"transmute(s1);\n" +" println!(\"ptr = {ptr:#x}, len = {len}, capacity = {capacity}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/manual.md:3 +msgid "You allocate and deallocate heap memory yourself." +msgstr "" + +#: src/memory-management/manual.md:5 +msgid "" +"If not done with care, this can lead to crashes, bugs, security " +"vulnerabilities, and memory leaks." +msgstr "" + +#: src/memory-management/manual.md:7 +msgid "C Example" +msgstr "" + +#: src/memory-management/manual.md:9 +msgid "You must call `free` on every pointer you allocate with `malloc`:" +msgstr "" + +#: src/memory-management/manual.md:11 +msgid "" +"```c\n" +"void foo(size_t n) {\n" +" int* int_array = malloc(n * sizeof(int));\n" +" //\n" +" // ... lots of code\n" +" //\n" +" free(int_array);\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/manual.md:21 +msgid "" +"Memory is leaked if the function returns early between `malloc` and `free`: " +"the pointer is lost and we cannot deallocate the memory. Worse, freeing the " +"pointer twice, or accessing a freed pointer can lead to exploitable security " +"vulnerabilities." +msgstr "" + +#: src/memory-management/scope-based.md:3 +msgid "" +"Constructors and destructors let you hook into the lifetime of an object." +msgstr "" + +#: src/memory-management/scope-based.md:5 +msgid "" +"By wrapping a pointer in an object, you can free memory when the object is " +"destroyed. The compiler guarantees that this happens, even if an exception " +"is raised." +msgstr "" + +#: src/memory-management/scope-based.md:9 +msgid "" +"This is often called _resource acquisition is initialization_ (RAII) and " +"gives you smart pointers." +msgstr "" + +#: src/memory-management/scope-based.md:12 +msgid "C++ Example" +msgstr "" + +#: src/memory-management/scope-based.md:14 +msgid "" +"```c++\n" +"void say_hello(std::unique_ptr person) {\n" +" std::cout << \"Hello \" << person->name << std::endl;\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/scope-based.md:20 +msgid "" +"The `std::unique_ptr` object is allocated on the stack, and points to memory " +"allocated on the heap." +msgstr "" + +#: src/memory-management/scope-based.md:22 +msgid "At the end of `say_hello`, the `std::unique_ptr` destructor will run." +msgstr "" + +#: src/memory-management/scope-based.md:23 +msgid "The destructor frees the `Person` object it points to." +msgstr "" + +#: src/memory-management/scope-based.md:25 +msgid "" +"Special move constructors are used when passing ownership to a function:" +msgstr "" + +#: src/memory-management/scope-based.md:27 +msgid "" +"```c++\n" +"std::unique_ptr person = find_person(\"Carla\");\n" +"say_hello(std::move(person));\n" +"```" +msgstr "" + +#: src/memory-management/garbage-collection.md:1 +msgid "Automatic Memory Management" +msgstr "" + +#: src/memory-management/garbage-collection.md:3 +msgid "" +"An alternative to manual and scope-based memory management is automatic " +"memory management:" +msgstr "" + +#: src/memory-management/garbage-collection.md:6 +msgid "The programmer never allocates or deallocates memory explicitly." +msgstr "" + +#: src/memory-management/garbage-collection.md:7 +msgid "" +"A garbage collector finds unused memory and deallocates it for the " +"programmer." +msgstr "" + +#: src/memory-management/garbage-collection.md:9 +msgid "Java Example" +msgstr "" + +#: src/memory-management/garbage-collection.md:11 +msgid "The `person` object is not deallocated after `sayHello` returns:" +msgstr "" + +#: src/memory-management/garbage-collection.md:13 +msgid "" +"```java\n" +"void sayHello(Person person) {\n" +" System.out.println(\"Hello \" + person.getName());\n" +"}\n" +"```" +msgstr "" + +#: src/memory-management/rust.md:1 +msgid "Memory Management in Rust" +msgstr "" + +#: src/memory-management/rust.md:3 +msgid "Memory management in Rust is a mix:" +msgstr "" + +#: src/memory-management/rust.md:5 +msgid "Safe and correct like Java, but without a garbage collector." +msgstr "" + +#: src/memory-management/rust.md:6 +msgid "" +"Depending on which abstraction (or combination of abstractions) you choose, " +"can be a single unique pointer, reference counted, or atomically reference " +"counted." +msgstr "" + +#: src/memory-management/rust.md:7 +msgid "Scope-based like C++, but the compiler enforces full adherence." +msgstr "" + +#: src/memory-management/rust.md:8 +msgid "" +"A Rust user can choose the right abstraction for the situation, some even " +"have no cost at runtime like C." +msgstr "" + +#: src/memory-management/rust.md:10 +msgid "Rust achieves this by modeling _ownership_ explicitly." +msgstr "" + +#: src/memory-management/rust.md:14 +msgid "" +"If asked how at this point, you can mention that in Rust this is usually " +"handled by RAII wrapper types such as [Box](https://doc.rust-lang.org/std/" +"boxed/struct.Box.html), [Vec](https://doc.rust-lang.org/std/vec/struct.Vec." +"html), [Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html), or [Arc]" +"(https://doc.rust-lang.org/std/sync/struct.Arc.html). These encapsulate " +"ownership and memory allocation via various means, and prevent the potential " +"errors in C." +msgstr "" + +#: src/memory-management/rust.md:16 +msgid "" +"You may be asked about destructors here, the [Drop](https://doc.rust-lang." +"org/std/ops/trait.Drop.html) trait is the Rust equivalent." +msgstr "" + +#: src/memory-management/comparison.md:3 +msgid "Here is a rough comparison of the memory management techniques." +msgstr "" + +#: src/memory-management/comparison.md:5 +msgid "Pros of Different Memory Management Techniques" +msgstr "" + +#: src/memory-management/comparison.md:7 src/memory-management/comparison.md:22 +msgid "Manual like C:" +msgstr "" + +#: src/memory-management/comparison.md:8 src/memory-management/comparison.md:14 +#: src/memory-management/comparison.md:17 +msgid "No runtime overhead." +msgstr "" + +#: src/memory-management/comparison.md:9 src/memory-management/comparison.md:26 +msgid "Automatic like Java:" +msgstr "" + +#: src/memory-management/comparison.md:10 +msgid "Fully automatic." +msgstr "" + +#: src/memory-management/comparison.md:11 +#: src/memory-management/comparison.md:18 +msgid "Safe and correct." +msgstr "" + +#: src/memory-management/comparison.md:12 +#: src/memory-management/comparison.md:29 +msgid "Scope-based like C++:" +msgstr "" + +#: src/memory-management/comparison.md:13 +msgid "Partially automatic." +msgstr "" + +#: src/memory-management/comparison.md:15 +msgid "Compiler-enforced scope-based like Rust:" +msgstr "" + +#: src/memory-management/comparison.md:16 +msgid "Enforced by compiler." +msgstr "" + +#: src/memory-management/comparison.md:20 +msgid "Cons of Different Memory Management Techniques" +msgstr "" + +#: src/memory-management/comparison.md:23 +msgid "Use-after-free." +msgstr "" + +#: src/memory-management/comparison.md:24 +msgid "Double-frees." +msgstr "" + +#: src/memory-management/comparison.md:25 +msgid "Memory leaks." +msgstr "" + +#: src/memory-management/comparison.md:27 +msgid "Garbage collection pauses." +msgstr "" + +#: src/memory-management/comparison.md:28 +msgid "Destructor delays." +msgstr "" + +#: src/memory-management/comparison.md:30 +msgid "Complex, opt-in by programmer (on C++)." +msgstr "" + +#: src/memory-management/comparison.md:31 +msgid "Circular references can lead to memory leaks" +msgstr "" + +#: src/memory-management/comparison.md:32 +msgid "Potential runtime overhead" +msgstr "" + +#: src/memory-management/comparison.md:33 +msgid "Compiler-enforced and scope-based like Rust:" +msgstr "" + +#: src/memory-management/comparison.md:34 +msgid "Some upfront complexity." +msgstr "" + +#: src/memory-management/comparison.md:35 +msgid "Can reject valid programs." +msgstr "" + +#: src/ownership.md:3 +msgid "" +"All variable bindings have a _scope_ where they are valid and it is an error " +"to use a variable outside its scope:" +msgstr "" + +#: src/ownership.md:6 +msgid "" +"```rust,editable,compile_fail\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" {\n" +" let p = Point(3, 4);\n" +" println!(\"x: {}\", p.0);\n" +" }\n" +" println!(\"y: {}\", p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership.md:18 +msgid "" +"At the end of the scope, the variable is _dropped_ and the data is freed." +msgstr "" + +#: src/ownership.md:19 +msgid "A destructor can run here to free up resources." +msgstr "" + +#: src/ownership.md:20 +msgid "We say that the variable _owns_ the value." +msgstr "" + +#: src/ownership/move-semantics.md:3 +msgid "An assignment will transfer _ownership_ between variables:" +msgstr "" + +#: src/ownership/move-semantics.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Hello!\");\n" +" let s2: String = s1;\n" +" println!(\"s2: {s2}\");\n" +" // println!(\"s1: {s1}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/move-semantics.md:14 +msgid "The assignment of `s1` to `s2` transfers ownership." +msgstr "" + +#: src/ownership/move-semantics.md:15 +msgid "When `s1` goes out of scope, nothing happens: it does not own anything." +msgstr "" + +#: src/ownership/move-semantics.md:16 +msgid "When `s2` goes out of scope, the string data is freed." +msgstr "" + +#: src/ownership/move-semantics.md:17 +msgid "There is always _exactly_ one variable binding which owns a value." +msgstr "" + +#: src/ownership/move-semantics.md:21 +msgid "" +"Mention that this is the opposite of the defaults in C++, which copies by " +"value unless you use `std::move` (and the move constructor is defined!)." +msgstr "" + +#: src/ownership/move-semantics.md:23 +msgid "" +"It is only the ownership that moves. Whether any machine code is generated " +"to manipulate the data itself is a matter of optimization, and such copies " +"are aggressively optimized away." +msgstr "" + +#: src/ownership/move-semantics.md:25 +msgid "" +"Simple values (such as integers) can be marked `Copy` (see later slides)." +msgstr "" + +#: src/ownership/move-semantics.md:27 +msgid "In Rust, clones are explicit (by using `clone`)." +msgstr "" + +#: src/ownership/moved-strings-rust.md:3 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let s1: String = String::from(\"Rust\");\n" +" let s2: String = s1;\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:10 +msgid "The heap data from `s1` is reused for `s2`." +msgstr "" + +#: src/ownership/moved-strings-rust.md:11 +msgid "When `s1` goes out of scope, nothing happens (it has been moved from)." +msgstr "" + +#: src/ownership/moved-strings-rust.md:13 +msgid "Before move to `s2`:" +msgstr "" + +#: src/ownership/moved-strings-rust.md:15 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+-----+-->| R | u | s | t | :\n" +": | len | 4 | : : +----+----+----+----+ :\n" +": | capacity | 4 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - - - -'\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moved-strings-rust.md:30 +msgid "After move to `s2`:" +msgstr "" + +#: src/ownership/moved-strings-rust.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - - - -.\n" +": : : :\n" +": s1 \"(inaccessible)\" : : :\n" +": +-----------+-------+ : : +----+----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| R | u | s | t | :\n" +": | len | 4 | : | : +----+----+----+----+ :\n" +": | capacity | 4 | : | : :\n" +": +-----------+-------+ : | : :\n" +": : | `- - - - - - - - - - - - - -'\n" +": s2 : |\n" +": +-----------+-------+ : |\n" +": | ptr | o---+---+--'\n" +": | len | 4 | :\n" +": | capacity | 4 | :\n" +": +-----------+-------+ :\n" +": :\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:1 +#, fuzzy +msgid "Extra Work in Modern C++" +msgstr "現代C++の二重解放" + +#: src/ownership/double-free-modern-cpp.md:3 +msgid "Modern C++ solves this differently:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:5 +msgid "" +"```c++\n" +"std::string s1 = \"Cpp\";\n" +"std::string s2 = s1; // Duplicate the data in s1.\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:10 +msgid "" +"The heap data from `s1` is duplicated and `s2` gets its own independent copy." +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:11 +msgid "When `s1` and `s2` go out of scope, they each free their own memory." +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:13 +msgid "Before copy-assignment:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:16 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:30 +msgid "After copy-assignment:" +msgstr "" + +#: src/ownership/double-free-modern-cpp.md:32 +msgid "" +"```bob\n" +" Stack Heap\n" +".- - - - - - - - - - - - - -. .- - - - - - - - - - - -.\n" +": : : :\n" +": s1 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+--+--+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : : :\n" +": s2 : : :\n" +": +-----------+-------+ : : +----+----+----+ :\n" +": | ptr | o---+---+-----+-->| C | p | p | :\n" +": | len | 3 | : : +----+----+----+ :\n" +": | capacity | 3 | : : :\n" +": +-----------+-------+ : : :\n" +": : `- - - - - - - - - - - -'\n" +"`- - - - - - - - - - - - - -'\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:3 +msgid "" +"When you pass a value to a function, the value is assigned to the function " +"parameter. This transfers ownership:" +msgstr "" + +#: src/ownership/moves-function-calls.md:6 +msgid "" +"```rust,editable\n" +"fn say_hello(name: String) {\n" +" println!(\"Hello {name}\")\n" +"}\n" +"\n" +"fn main() {\n" +" let name = String::from(\"Alice\");\n" +" say_hello(name);\n" +" // say_hello(name);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/moves-function-calls.md:20 +msgid "" +"With the first call to `say_hello`, `main` gives up ownership of `name`. " +"Afterwards, `name` cannot be used anymore within `main`." +msgstr "" + +#: src/ownership/moves-function-calls.md:21 +msgid "" +"The heap memory allocated for `name` will be freed at the end of the " +"`say_hello` function." +msgstr "" + +#: src/ownership/moves-function-calls.md:22 +msgid "" +"`main` can retain ownership if it passes `name` as a reference (`&name`) and " +"if `say_hello` accepts a reference as a parameter." +msgstr "" + +#: src/ownership/moves-function-calls.md:23 +msgid "" +"Alternatively, `main` can pass a clone of `name` in the first call (`name." +"clone()`)." +msgstr "" + +#: src/ownership/moves-function-calls.md:24 +msgid "" +"Rust makes it harder than C++ to inadvertently create copies by making move " +"semantics the default, and by forcing programmers to make clones explicit." +msgstr "" + +#: src/ownership/copy-clone.md:3 +msgid "" +"While move semantics are the default, certain types are copied by default:" +msgstr "" + +#: src/ownership/copy-clone.md:5 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let x = 42;\n" +" let y = x;\n" +" println!(\"x: {x}\");\n" +" println!(\"y: {y}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:14 +msgid "These types implement the `Copy` trait." +msgstr "" + +#: src/ownership/copy-clone.md:16 +msgid "You can opt-in your own types to use copy semantics:" +msgstr "" + +#: src/ownership/copy-clone.md:18 +msgid "" +"```rust,editable\n" +"#[derive(Copy, Clone, Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = p1;\n" +" println!(\"p1: {p1:?}\");\n" +" println!(\"p2: {p2:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/copy-clone.md:30 +msgid "After the assignment, both `p1` and `p2` own their own data." +msgstr "" + +#: src/ownership/copy-clone.md:31 +msgid "We can also use `p1.clone()` to explicitly copy the data." +msgstr "" + +#: src/ownership/copy-clone.md:35 +msgid "Copying and cloning are not the same thing:" +msgstr "" + +#: src/ownership/copy-clone.md:37 +msgid "" +"Copying refers to bitwise copies of memory regions and does not work on " +"arbitrary objects." +msgstr "" + +#: src/ownership/copy-clone.md:38 +msgid "" +"Copying does not allow for custom logic (unlike copy constructors in C++)." +msgstr "" + +#: src/ownership/copy-clone.md:39 +msgid "" +"Cloning is a more general operation and also allows for custom behavior by " +"implementing the `Clone` trait." +msgstr "" + +#: src/ownership/copy-clone.md:40 +msgid "Copying does not work on types that implement the `Drop` trait." +msgstr "" + +#: src/ownership/copy-clone.md:42 src/ownership/lifetimes-function-calls.md:29 +msgid "In the above example, try the following:" +msgstr "" + +#: src/ownership/copy-clone.md:44 +msgid "" +"Add a `String` field to `struct Point`. It will not compile because `String` " +"is not a `Copy` type." +msgstr "" + +#: src/ownership/copy-clone.md:45 +msgid "" +"Remove `Copy` from the `derive` attribute. The compiler error is now in the " +"`println!` for `p1`." +msgstr "" + +#: src/ownership/copy-clone.md:46 +msgid "Show that it works if you clone `p1` instead." +msgstr "" + +#: src/ownership/copy-clone.md:48 +msgid "" +"If students ask about `derive`, it is sufficient to say that this is a way " +"to generate code in Rust at compile time. In this case the default " +"implementations of `Copy` and `Clone` traits are generated." +msgstr "" + +#: src/ownership/borrowing.md:3 +msgid "" +"Instead of transferring ownership when calling a function, you can let a " +"function _borrow_ the value:" +msgstr "" + +#: src/ownership/borrowing.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn add(p1: &Point, p2: &Point) -> Point {\n" +" Point(p1.0 + p2.0, p1.1 + p2.1)\n" +"}\n" +"\n" +"fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/borrowing.md:22 +msgid "The `add` function _borrows_ two points and returns a new point." +msgstr "" + +#: src/ownership/borrowing.md:23 +msgid "The caller retains ownership of the inputs." +msgstr "" + +#: src/ownership/borrowing.md:27 +msgid "Notes on stack returns:" +msgstr "" + +#: src/ownership/borrowing.md:28 +msgid "" +"Demonstrate that the return from `add` is cheap because the compiler can " +"eliminate the copy operation. Change the above code to print stack addresses " +"and run it on the [Playground](https://play.rust-lang.org/) or look at the " +"assembly in [Godbolt](https://rust.godbolt.org/). In the \"DEBUG\" " +"optimization level, the addresses should change, while they stay the same " +"when changing to the \"RELEASE\" setting:" +msgstr "" + +#: src/ownership/borrowing.md:30 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn add(p1: &Point, p2: &Point) -> Point {\n" +" let p = Point(p1.0 + p2.0, p1.1 + p2.1);\n" +" println!(\"&p.0: {:p}\", &p.0);\n" +" p\n" +"}\n" +"\n" +"pub fn main() {\n" +" let p1 = Point(3, 4);\n" +" let p2 = Point(10, 20);\n" +" let p3 = add(&p1, &p2);\n" +" println!(\"&p3.0: {:p}\", &p3.0);\n" +" println!(\"{p1:?} + {p2:?} = {p3:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/borrowing.md:48 +msgid "The Rust compiler can do return value optimization (RVO)." +msgstr "" + +#: src/ownership/borrowing.md:49 +msgid "" +"In C++, copy elision has to be defined in the language specification because " +"constructors can have side effects. In Rust, this is not an issue at all. If " +"RVO did not happen, Rust will always perform a simple and efficient `memcpy` " +"copy." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:3 +msgid "Rust puts constraints on the ways you can borrow values:" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:5 +msgid "You can have one or more `&T` values at any given time, _or_" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:6 +msgid "You can have exactly one `&mut T` value." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let mut a: i32 = 10;\n" +" let b: &i32 = &a;\n" +"\n" +" {\n" +" let c: &mut i32 = &mut a;\n" +" *c = 20;\n" +" }\n" +"\n" +" println!(\"a: {a}\");\n" +" println!(\"b: {b}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/shared-unique-borrows.md:25 +msgid "" +"The above code does not compile because `a` is borrowed as mutable (through " +"`c`) and as immutable (through `b`) at the same time." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:26 +msgid "" +"Move the `println!` statement for `b` before the scope that introduces `c` " +"to make the code compile." +msgstr "" + +#: src/ownership/shared-unique-borrows.md:27 +msgid "" +"After that change, the compiler realizes that `b` is only ever used before " +"the new mutable borrow of `a` through `c`. This is a feature of the borrow " +"checker called \"non-lexical lifetimes\"." +msgstr "" + +#: src/ownership/lifetimes.md:3 +msgid "A borrowed value has a _lifetime_:" +msgstr "" + +#: src/ownership/lifetimes.md:5 +msgid "The lifetime can be implicit: `add(p1: &Point, p2: &Point) -> Point`." +msgstr "" + +#: src/ownership/lifetimes.md:6 +msgid "Lifetimes can also be explicit: `&'a Point`, `&'document str`." +msgstr "" + +#: src/ownership/lifetimes.md:7 src/ownership/lifetimes-function-calls.md:23 +msgid "" +"Read `&'a Point` as \"a borrowed `Point` which is valid for at least the " +"lifetime `a`\"." +msgstr "" + +#: src/ownership/lifetimes.md:9 +msgid "" +"Lifetimes are always inferred by the compiler: you cannot assign a lifetime " +"yourself." +msgstr "" + +#: src/ownership/lifetimes.md:11 +msgid "" +"Lifetime annotations create constraints; the compiler verifies that there is " +"a valid solution." +msgstr "" + +#: src/ownership/lifetimes.md:13 +msgid "" +"Lifetimes for function arguments and return values must be fully specified, " +"but Rust allows lifetimes to be elided in most cases with [a few simple " +"rules](https://doc.rust-lang.org/nomicon/lifetime-elision.html)." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:3 +msgid "" +"In addition to borrowing its arguments, a function can return a borrowed " +"value:" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p2: Point = Point(20, 20);\n" +" let p3: &Point = left_most(&p1, &p2);\n" +" println!(\"left-most point: {:?}\", p3);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:21 +msgid "`'a` is a generic parameter, it is inferred by the compiler." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:22 +msgid "Lifetimes start with `'` and `'a` is a typical default name." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:25 +msgid "" +"The _at least_ part is important when parameters are in different scopes." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:31 +msgid "" +"Move the declaration of `p2` and `p3` into a new scope (`{ ... }`), " +"resulting in the following code:" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:32 +msgid "" +"```rust,ignore\n" +"#[derive(Debug)]\n" +"struct Point(i32, i32);\n" +"\n" +"fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {\n" +" if p1.0 < p2.0 { p1 } else { p2 }\n" +"}\n" +"\n" +"fn main() {\n" +" let p1: Point = Point(10, 10);\n" +" let p3: &Point;\n" +" {\n" +" let p2: Point = Point(20, 20);\n" +" p3 = left_most(&p1, &p2);\n" +" }\n" +" println!(\"left-most point: {:?}\", p3);\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:50 +msgid "Note how this does not compile since `p3` outlives `p2`." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:52 +msgid "" +"Reset the workspace and change the function signature to `fn left_most<'a, " +"'b>(p1: &'a Point, p2: &'a Point) -> &'b Point`. This will not compile " +"because the relationship between the lifetimes `'a` and `'b` is unclear." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:53 +msgid "Another way to explain it:" +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:54 +msgid "" +"Two references to two values are borrowed by a function and the function " +"returns another reference." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:56 +msgid "" +"It must have come from one of those two inputs (or from a global variable)." +msgstr "" + +#: src/ownership/lifetimes-function-calls.md:57 +msgid "" +"Which one is it? The compiler needs to know, so at the call site the " +"returned reference is not used for longer than a variable from where the " +"reference came from." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:3 +msgid "" +"If a data type stores borrowed data, it must be annotated with a lifetime:" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:5 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Highlight<'doc>(&'doc str);\n" +"\n" +"fn erase(text: String) {\n" +" println!(\"Bye {text}!\");\n" +"}\n" +"\n" +"fn main() {\n" +" let text = String::from(\"The quick brown fox jumps over the lazy dog." +"\");\n" +" let fox = Highlight(&text[4..19]);\n" +" let dog = Highlight(&text[35..43]);\n" +" // erase(text);\n" +" println!(\"{fox:?}\");\n" +" println!(\"{dog:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:25 +msgid "" +"In the above example, the annotation on `Highlight` enforces that the data " +"underlying the contained `&str` lives at least as long as any instance of " +"`Highlight` that uses that data." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:26 +msgid "" +"If `text` is consumed before the end of the lifetime of `fox` (or `dog`), " +"the borrow checker throws an error." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:27 +msgid "" +"Types with borrowed data force users to hold on to the original data. This " +"can be useful for creating lightweight views, but it generally makes them " +"somewhat harder to use." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:28 +msgid "When possible, make data structures own their data directly." +msgstr "" + +#: src/ownership/lifetimes-data-structures.md:29 +msgid "" +"Some structs with multiple references inside can have more than one lifetime " +"annotation. This can be necessary if there is a need to describe lifetime " +"relationships between the references themselves, in addition to the lifetime " +"of the struct itself. Those are very advanced use cases." +msgstr "" + #: src/exercises/day-2/morning.md:1 msgid "Day 2: Morning Exercises" msgstr "" @@ -6471,6 +6544,763 @@ msgstr "" msgid "Multiple structs and enums for a drawing library." msgstr "" +#: src/exercises/day-2/book-library.md:3 +msgid "" +"We will learn much more about structs and the `Vec` type tomorrow. For " +"now, you just need to know part of its API:" +msgstr "" + +#: src/exercises/day-2/book-library.md:6 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let mut vec = vec![10, 20];\n" +" vec.push(30);\n" +" let midpoint = vec.len() / 2;\n" +" println!(\"middle value: {}\", vec[midpoint]);\n" +" for item in &vec {\n" +" println!(\"item: {item}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/book-library.md:18 +msgid "" +"Use this to model a library's book collection. Copy the code below to " +" and update the types to make it compile:" +msgstr "" + +#: src/exercises/day-2/book-library.md:21 +msgid "" +"```rust,should_panic\n" +"struct Library {\n" +" books: Vec,\n" +"}\n" +"\n" +"struct Book {\n" +" title: String,\n" +" year: u16,\n" +"}\n" +"\n" +"impl Book {\n" +" // This is a constructor, used below.\n" +" fn new(title: &str, year: u16) -> Book {\n" +" Book {\n" +" title: String::from(title),\n" +" year,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// Implement the methods below. Update the `self` parameter to\n" +"// indicate the method's required level of ownership over the object:\n" +"//\n" +"// - `&self` for shared read-only access,\n" +"// - `&mut self` for unique and mutable access,\n" +"// - `self` for unique access by value.\n" +"impl Library {\n" +" fn new() -> Library {\n" +" todo!(\"Initialize and return a `Library` value\")\n" +" }\n" +"\n" +" //fn len(self) -> usize {\n" +" // todo!(\"Return the length of `self.books`\")\n" +" //}\n" +"\n" +" //fn is_empty(self) -> bool {\n" +" // todo!(\"Return `true` if `self.books` is empty\")\n" +" //}\n" +"\n" +" //fn add_book(self, book: Book) {\n" +" // todo!(\"Add a new book to `self.books`\")\n" +" //}\n" +"\n" +" //fn print_books(self) {\n" +" // todo!(\"Iterate over `self.books` and each book's title and " +"year\")\n" +" //}\n" +"\n" +" //fn oldest_book(self) -> Option<&Book> {\n" +" // todo!(\"Return a reference to the oldest book (if any)\")\n" +" //}\n" +"}\n" +"\n" +"// This shows the desired behavior. Uncomment the code below and\n" +"// implement the missing methods. You will need to update the\n" +"// method signatures, including the \"self\" parameter! You may\n" +"// also need to update the variable bindings within main.\n" +"fn main() {\n" +" let library = Library::new();\n" +"\n" +" //println!(\"The library is empty: library.is_empty() -> {}\", library." +"is_empty());\n" +" //\n" +" //library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" +" //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " +"1865));\n" +" //\n" +" //println!(\"The library is no longer empty: library.is_empty() -> {}\", " +"library.is_empty());\n" +" //\n" +" //\n" +" //library.print_books();\n" +" //\n" +" //match library.oldest_book() {\n" +" // Some(book) => println!(\"The oldest book is {}\", book.title),\n" +" // None => println!(\"The library is empty!\"),\n" +" //}\n" +" //\n" +" //println!(\"The library has {} books\", library.len());\n" +" //library.print_books();\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/book-library.md:102 +msgid "[Solution](solutions-afternoon.md#designing-a-library)" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:3 +msgid "" +"The ownership model of Rust affects many APIs. An example of this is the " +"[`Iterator`](https://doc.rust-lang.org/std/iter/trait.Iterator.html) and " +"[`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html) " +"traits." +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:8 src/bare-metal/no_std.md:28 +msgid "`Iterator`" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:10 +msgid "" +"Traits are like interfaces: they describe behavior (methods) for a type. The " +"`Iterator` trait simply says that you can call `next` until you get `None` " +"back:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:13 +msgid "" +"```rust\n" +"pub trait Iterator {\n" +" type Item;\n" +" fn next(&mut self) -> Option;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:20 +msgid "You use this trait like this:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:22 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" println!(\"v[0]: {:?}\", iter.next());\n" +" println!(\"v[1]: {:?}\", iter.next());\n" +" println!(\"v[2]: {:?}\", iter.next());\n" +" println!(\"No more items: {:?}\", iter.next());\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:34 +msgid "What is the type returned by the iterator? Test your answer here:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:36 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![10, 20, 30];\n" +" let mut iter = v.iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:46 +msgid "Why is this type used?" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:48 +msgid "`IntoIterator`" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:50 +msgid "" +"The `Iterator` trait tells you how to _iterate_ once you have created an " +"iterator. The related trait `IntoIterator` tells you how to create the " +"iterator:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:53 +msgid "" +"```rust\n" +"pub trait IntoIterator {\n" +" type Item;\n" +" type IntoIter: Iterator;\n" +"\n" +" fn into_iter(self) -> Self::IntoIter;\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:62 +msgid "" +"The syntax here means that every implementation of `IntoIterator` must " +"declare two types:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:65 +msgid "`Item`: the type we iterate over, such as `i8`," +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:66 +msgid "`IntoIter`: the `Iterator` type returned by the `into_iter` method." +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:68 +msgid "" +"Note that `IntoIter` and `Item` are linked: the iterator must have the same " +"`Item` type, which means that it returns `Option`" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:71 +msgid "Like before, what is the type returned by the iterator?" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:73 +msgid "" +"```rust,editable,compile_fail\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::" +"from(\"bar\")];\n" +" let mut iter = v.into_iter();\n" +"\n" +" let v0: Option<..> = iter.next();\n" +" println!(\"v0: {v0:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:83 +msgid "`for` Loops" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:85 +msgid "" +"Now that we know both `Iterator` and `IntoIterator`, we can build `for` " +"loops. They call `into_iter()` on an expression and iterates over the " +"resulting iterator:" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:89 +msgid "" +"```rust,editable\n" +"fn main() {\n" +" let v: Vec = vec![String::from(\"foo\"), String::" +"from(\"bar\")];\n" +"\n" +" for word in &v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"\n" +" for word in v {\n" +" println!(\"word: {word}\");\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:103 +msgid "What is the type of `word` in each loop?" +msgstr "" + +#: src/exercises/day-2/iterators-and-ownership.md:105 +msgid "" +"Experiment with the code above and then consult the documentation for [`impl " +"IntoIterator for &Vec`](https://doc.rust-lang.org/std/vec/struct.Vec." +"html#impl-IntoIterator-for-%26'a+Vec%3CT,+A%3E) and [`impl IntoIterator for " +"Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html#impl-IntoIterator-" +"for-Vec%3CT,+A%3E) to check your answers." +msgstr "" + +#: src/structs.md:3 +msgid "Like C and C++, Rust has support for custom structs:" +msgstr "" + +#: src/structs.md:5 +msgid "" +"```rust,editable\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"fn main() {\n" +" let mut peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" peter.age = 28;\n" +" println!(\"{} is {} years old\", peter.name, peter.age);\n" +" \n" +" let jackie = Person {\n" +" name: String::from(\"Jackie\"),\n" +" ..peter\n" +" };\n" +" println!(\"{} is {} years old\", jackie.name, jackie.age);\n" +"}\n" +"```" +msgstr "" + +#: src/structs.md:33 +msgid "Structs work like in C or C++." +msgstr "" + +#: src/structs.md:34 +msgid "Like in C++, and unlike in C, no typedef is needed to define a type." +msgstr "" + +#: src/structs.md:35 +msgid "Unlike in C++, there is no inheritance between structs." +msgstr "" + +#: src/structs.md:36 +msgid "" +"Methods are defined in an `impl` block, which we will see in following " +"slides." +msgstr "" + +#: src/structs.md:37 +msgid "" +"This may be a good time to let people know there are different types of " +"structs. " +msgstr "" + +#: src/structs.md:38 +msgid "" +"Zero-sized structs `e.g., struct Foo;` might be used when implementing a " +"trait on some type but don’t have any data that you want to store in the " +"value itself. " +msgstr "" + +#: src/structs.md:39 +msgid "" +"The next slide will introduce Tuple structs, used when the field names are " +"not important." +msgstr "" + +#: src/structs.md:40 +msgid "" +"The syntax `..peter` allows us to copy the majority of the fields from the " +"old struct without having to explicitly type it all out. It must always be " +"the last element." +msgstr "" + +#: src/structs/tuple-structs.md:3 +msgid "If the field names are unimportant, you can use a tuple struct:" +msgstr "" + +#: src/structs/tuple-structs.md:5 +msgid "" +"```rust,editable\n" +"struct Point(i32, i32);\n" +"\n" +"fn main() {\n" +" let p = Point(17, 23);\n" +" println!(\"({}, {})\", p.0, p.1);\n" +"}\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:14 +msgid "This is often used for single-field wrappers (called newtypes):" +msgstr "" + +#: src/structs/tuple-structs.md:16 +msgid "" +"```rust,editable,compile_fail\n" +"struct PoundsOfForce(f64);\n" +"struct Newtons(f64);\n" +"\n" +"fn compute_thruster_force() -> PoundsOfForce {\n" +" todo!(\"Ask a rocket scientist at NASA\")\n" +"}\n" +"\n" +"fn set_thruster_force(force: Newtons) {\n" +" // ...\n" +"}\n" +"\n" +"fn main() {\n" +" let force = compute_thruster_force();\n" +" set_thruster_force(force);\n" +"}\n" +"\n" +"```" +msgstr "" + +#: src/structs/tuple-structs.md:37 +msgid "" +"Newtypes are a great way to encode additional information about the value in " +"a primitive type, for example:" +msgstr "" + +#: src/structs/tuple-structs.md:38 +msgid "The number is measured in some units: `Newtons` in the example above." +msgstr "" + +#: src/structs/tuple-structs.md:39 +msgid "" +"The value passed some validation when it was created, so you no longer have " +"to validate it again at every use: 'PhoneNumber(String)`or`OddNumber(u32)\\`." +msgstr "" + +#: src/structs/tuple-structs.md:40 +msgid "" +"Demonstrate how to add a `f64` value to a `Newtons` type by accessing the " +"single field in the newtype." +msgstr "" + +#: src/structs/tuple-structs.md:41 +msgid "" +"Rust generally doesn’t like inexplicit things, like automatic unwrapping or " +"for instance using booleans as integers." +msgstr "" + +#: src/structs/tuple-structs.md:42 +msgid "Operator overloading is discussed on Day 3 (generics)." +msgstr "" + +#: src/structs/tuple-structs.md:43 +msgid "" +"The example is a subtle reference to the [Mars Climate Orbiter](https://en." +"wikipedia.org/wiki/Mars_Climate_Orbiter) failure." +msgstr "" + +#: src/structs/field-shorthand.md:3 +msgid "" +"If you already have variables with the right names, then you can create the " +"struct using a shorthand:" +msgstr "" + +#: src/structs/field-shorthand.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn new(name: String, age: u8) -> Person {\n" +" Person { name, age }\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person::new(String::from(\"Peter\"), 27);\n" +" println!(\"{peter:?}\");\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:27 +msgid "" +"The `new` function could be written using `Self` as a type, as it is " +"interchangeable with the struct type name" +msgstr "" + +#: src/structs/field-shorthand.md:29 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"impl Person {\n" +" fn new(name: String, age: u8) -> Self {\n" +" Self { name, age }\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:41 +msgid "" +"Implement the `Default` trait for the struct. Define some fields and use the " +"default values for the other fields." +msgstr "" + +#: src/structs/field-shorthand.md:43 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"impl Default for Person {\n" +" fn default() -> Person {\n" +" Person {\n" +" name: \"Bot\".to_string(),\n" +" age: 0,\n" +" }\n" +" }\n" +"}\n" +"fn create_default() {\n" +" let tmp = Person {\n" +" ..Person::default()\n" +" };\n" +" let tmp = Person {\n" +" name: \"Sam\".to_string(),\n" +" ..Person::default()\n" +" };\n" +"}\n" +"```" +msgstr "" + +#: src/structs/field-shorthand.md:68 +msgid "Methods are defined in the `impl` block." +msgstr "" + +#: src/structs/field-shorthand.md:69 +msgid "" +"Use struct update syntax to define a new structure using `peter`. Note that " +"the variable `peter` will no longer be accessible afterwards." +msgstr "" + +#: src/structs/field-shorthand.md:70 +msgid "" +"Use `{:#?}` when printing structs to request the `Debug` representation." +msgstr "" + +#: src/methods.md:3 +msgid "" +"Rust allows you to associate functions with your new types. You do this with " +"an `impl` block:" +msgstr "" + +#: src/methods.md:6 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Person {\n" +" name: String,\n" +" age: u8,\n" +"}\n" +"\n" +"impl Person {\n" +" fn say_hello(&self) {\n" +" println!(\"Hello, my name is {}\", self.name);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let peter = Person {\n" +" name: String::from(\"Peter\"),\n" +" age: 27,\n" +" };\n" +" peter.say_hello();\n" +"}\n" +"```" +msgstr "" + +#: src/methods.md:31 +msgid "It can be helpful to introduce methods by comparing them to functions." +msgstr "" + +#: src/methods.md:32 +msgid "" +"Methods are called on an instance of a type (such as a struct or enum), the " +"first parameter represents the instance as `self`." +msgstr "" + +#: src/methods.md:33 +msgid "" +"Developers may choose to use methods to take advantage of method receiver " +"syntax and to help keep them more organized. By using methods we can keep " +"all the implementation code in one predictable place." +msgstr "" + +#: src/methods.md:34 +msgid "Point out the use of the keyword `self`, a method receiver." +msgstr "" + +#: src/methods.md:35 +msgid "" +"Show that it is an abbreviated term for `self: Self` and perhaps show how " +"the struct name could also be used." +msgstr "" + +#: src/methods.md:36 +msgid "" +"Explain that `Self` is a type alias for the type the `impl` block is in and " +"can be used elsewhere in the block." +msgstr "" + +#: src/methods.md:37 +msgid "" +"Note how `self` is used like other structs and dot notation can be used to " +"refer to individual fields." +msgstr "" + +#: src/methods.md:38 +msgid "" +"This might be a good time to demonstrate how the `&self` differs from `self` " +"by modifying the code and trying to run say_hello twice." +msgstr "" + +#: src/methods.md:39 +msgid "We describe the distinction between method receivers next." +msgstr "" + +#: src/methods/receiver.md:3 +msgid "" +"The `&self` above indicates that the method borrows the object immutably. " +"There are other possible receivers for a method:" +msgstr "" + +#: src/methods/receiver.md:6 +msgid "" +"`&self`: borrows the object from the caller using a shared and immutable " +"reference. The object can be used again afterwards." +msgstr "" + +#: src/methods/receiver.md:8 +msgid "" +"`&mut self`: borrows the object from the caller using a unique and mutable " +"reference. The object can be used again afterwards." +msgstr "" + +#: src/methods/receiver.md:10 +msgid "" +"`self`: takes ownership of the object and moves it away from the caller. The " +"method becomes the owner of the object. The object will be dropped " +"(deallocated) when the method returns, unless its ownership is explicitly " +"transmitted. Complete ownership does not automatically mean mutability." +msgstr "" + +#: src/methods/receiver.md:14 +msgid "`mut self`: same as above, but the method can mutate the object. " +msgstr "" + +#: src/methods/receiver.md:15 +msgid "" +"No receiver: this becomes a static method on the struct. Typically used to " +"create constructors which are called `new` by convention." +msgstr "" + +#: src/methods/receiver.md:18 +msgid "" +"Beyond variants on `self`, there are also [special wrapper types](https://" +"doc.rust-lang.org/reference/special-types-and-traits.html) allowed to be " +"receiver types, such as `Box`." +msgstr "" + +#: src/methods/receiver.md:24 +msgid "" +"Consider emphasizing \"shared and immutable\" and \"unique and mutable\". " +"These constraints always come together in Rust due to borrow checker rules, " +"and `self` is no exception. It isn't possible to reference a struct from " +"multiple locations and call a mutating (`&mut self`) method on it." +msgstr "" + +#: src/methods/example.md:3 +msgid "" +"```rust,editable\n" +"#[derive(Debug)]\n" +"struct Race {\n" +" name: String,\n" +" laps: Vec,\n" +"}\n" +"\n" +"impl Race {\n" +" fn new(name: &str) -> Race { // No receiver, a static method\n" +" Race { name: String::from(name), laps: Vec::new() }\n" +" }\n" +"\n" +" fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write " +"access to self\n" +" self.laps.push(lap);\n" +" }\n" +"\n" +" fn print_laps(&self) { // Shared and read-only borrowed access to self\n" +" println!(\"Recorded {} laps for {}:\", self.laps.len(), self.name);\n" +" for (idx, lap) in self.laps.iter().enumerate() {\n" +" println!(\"Lap {idx}: {lap} sec\");\n" +" }\n" +" }\n" +"\n" +" fn finish(self) { // Exclusive ownership of self\n" +" let total = self.laps.iter().sum::();\n" +" println!(\"Race {} is finished, total lap time: {}\", self.name, " +"total);\n" +" }\n" +"}\n" +"\n" +"fn main() {\n" +" let mut race = Race::new(\"Monaco Grand Prix\");\n" +" race.add_lap(70);\n" +" race.add_lap(68);\n" +" race.print_laps();\n" +" race.add_lap(71);\n" +" race.print_laps();\n" +" race.finish();\n" +" // race.add_lap(42);\n" +"}\n" +"```" +msgstr "" + +#: src/methods/example.md:47 +msgid "All four methods here use a different method receiver." +msgstr "" + +#: src/methods/example.md:48 +msgid "" +"You can point out how that changes what the function can do with the " +"variable values and if/how it can be used again in `main`." +msgstr "" + +#: src/methods/example.md:49 +msgid "" +"You can showcase the error that appears when trying to call `finish` twice." +msgstr "" + +#: src/methods/example.md:50 +msgid "" +"Note that although the method receivers are different, the non-static " +"functions are called the same way in the main body. Rust enables automatic " +"referencing and dereferencing when calling methods. Rust automatically adds " +"in the `&`, `*`, `muts` so that that object matches the method signature." +msgstr "" + +#: src/methods/example.md:51 +msgid "" +"You might point out that `print_laps` is using a vector that is iterated " +"over. We describe vectors in more detail in the afternoon. " +msgstr "" + +#: src/exercises/day-2/afternoon.md:1 +msgid "Day 2: Afternoon Exercises" +msgstr "" + +#: src/exercises/day-2/afternoon.md:3 +msgid "The exercises for this afternoon will focus on strings and iterators." +msgstr "" + #: src/exercises/day-2/health-statistics.md:3 msgid "" "You're working on implementing a health-monitoring system. As part of that, " @@ -6496,14 +7326,28 @@ msgid "" "// TODO: remove this when you're done with your implementation.\n" "#![allow(unused_variables, dead_code)]\n" "\n" -"struct User {\n" +"pub struct User {\n" " name: String,\n" " age: u32,\n" -" weight: f32,\n" +" height: f32,\n" +" visit_count: usize,\n" +" last_blood_pressure: Option<(u32, u32)>,\n" +"}\n" +"\n" +"pub struct Measurements {\n" +" height: f32,\n" +" blood_pressure: (u32, u32),\n" +"}\n" +"\n" +"pub struct HealthReport<'a> {\n" +" patient_name: &'a str,\n" +" visit_count: u32,\n" +" height_change: f32,\n" +" blood_pressure_change: Option<(i32, i32)>,\n" "}\n" "\n" "impl User {\n" -" pub fn new(name: String, age: u32, weight: f32) -> Self {\n" +" pub fn new(name: String, age: u32, height: f32) -> Self {\n" " unimplemented!()\n" " }\n" "\n" @@ -6515,7 +7359,11 @@ msgid "" " unimplemented!()\n" " }\n" "\n" -" pub fn weight(&self) -> f32 {\n" +" pub fn height(&self) -> f32 {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn doctor_visits(&self) -> u32 {\n" " unimplemented!()\n" " }\n" "\n" @@ -6523,7 +7371,12 @@ msgid "" " unimplemented!()\n" " }\n" "\n" -" pub fn set_weight(&mut self, new_weight: f32) {\n" +" pub fn set_height(&mut self, new_height: f32) {\n" +" unimplemented!()\n" +" }\n" +"\n" +" pub fn visit_doctor(&mut self, measurements: Measurements) -> " +"HealthReport {\n" " unimplemented!()\n" " }\n" "}\n" @@ -6534,9 +7387,9 @@ msgid "" "}\n" "\n" "#[test]\n" -"fn test_weight() {\n" +"fn test_height() {\n" " let bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" -" assert_eq!(bob.weight(), 155.2);\n" +" assert_eq!(bob.height(), 155.2);\n" "}\n" "\n" "#[test]\n" @@ -6546,627 +7399,30 @@ msgid "" " bob.set_age(33);\n" " assert_eq!(bob.age(), 33);\n" "}\n" -"```" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:1 -msgid "Polygon Struct" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:3 -msgid "" -"We will create a `Polygon` struct which contain some points. Copy the code " -"below to and fill in the missing methods to " -"make the tests pass:" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:7 -msgid "" -"```rust\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]\n" "\n" -"pub struct Point {\n" -" // add fields\n" -"}\n" +"#[test]\n" +"fn test_visit() {\n" +" let mut bob = User::new(String::from(\"Bob\"), 32, 155.2);\n" +" assert_eq!(bob.doctor_visits(), 0);\n" +" let report = bob.visit_doctor(Measurements {\n" +" height: 156.1,\n" +" blood_pressure: (120, 80),\n" +" });\n" +" assert_eq!(report.patient_name, \"Bob\");\n" +" assert_eq!(report.visit_count, 1);\n" +" assert_eq!(report.blood_pressure_change, None);\n" "\n" -"impl Point {\n" -" // add methods\n" -"}\n" +" let report = bob.visit_doctor(Measurements {\n" +" height: 156.1,\n" +" blood_pressure: (115, 76),\n" +" });\n" "\n" -"pub struct Polygon {\n" -" // add fields\n" -"}\n" -"\n" -"impl Polygon {\n" -" // add methods\n" -"}\n" -"\n" -"pub struct Circle {\n" -" // add fields\n" -"}\n" -"\n" -"impl Circle {\n" -" // add methods\n" -"}\n" -"\n" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" -"}\n" -"\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;\n" -"\n" -" fn round_two_digits(x: f64) -> f64 {\n" -" (x * 100.0).round() / 100.0\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_magnitude() {\n" -" let p1 = Point::new(12, 13);\n" -" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_dist() {\n" -" let p1 = Point::new(10, 10);\n" -" let p2 = Point::new(14, 13);\n" -" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_add() {\n" -" let p1 = Point::new(16, 16);\n" -" let p2 = p1 + Point::new(-4, 3);\n" -" assert_eq!(p2, Point::new(12, 19));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_left_most_point() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -" assert_eq!(poly.left_most_point(), Some(p1));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_iter() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -"\n" -" let points = poly.iter().cloned().collect::>();\n" -" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_shape_perimeters() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::from(poly),\n" -" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" -" ];\n" -" let perimeters = shapes\n" -" .iter()\n" -" .map(Shape::perimeter)\n" -" .map(round_two_digits)\n" -" .collect::>();\n" -" assert_eq!(perimeters, vec![15.48, 31.42]);\n" -" }\n" -"}\n" -"\n" -"#[allow(dead_code)]\n" -"fn main() {}\n" -"```" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:117 -msgid "" -"Since the method signatures are missing from the problem statements, the key " -"part of the exercise is to specify those correctly. You don't have to modify " -"the tests." -msgstr "" - -#: src/exercises/day-2/points-polygons.md:120 -msgid "Other interesting parts of the exercise:" -msgstr "" - -#: src/exercises/day-2/points-polygons.md:122 -msgid "" -"Derive a `Copy` trait for some structs, as in tests the methods sometimes " -"don't borrow their arguments." -msgstr "" - -#: src/exercises/day-2/points-polygons.md:123 -msgid "" -"Discover that `Add` trait must be implemented for two objects to be addable " -"via \"+\". Note that we do not discuss generics until Day 3." -msgstr "" - -#: src/control-flow.md:3 -msgid "" -"As we have seen, `if` is an expression in Rust. It is used to conditionally " -"evaluate one of two blocks, but the blocks can have a value which then " -"becomes the value of the `if` expression. Other control flow expressions " -"work similarly in Rust." -msgstr "" - -#: src/control-flow/blocks.md:3 -msgid "" -"A block in Rust has a value and a type: the value is the last expression of " -"the block:" -msgstr "" - -#: src/control-flow/blocks.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let x = {\n" -" let y = 10;\n" -" println!(\"y: {y}\");\n" -" let z = {\n" -" let w = {\n" -" 3 + 4\n" -" };\n" -" println!(\"w: {w}\");\n" -" y * w\n" -" };\n" -" println!(\"z: {z}\");\n" -" z - y\n" -" };\n" -" println!(\"x: {x}\");\n" +" assert_eq!(report.visit_count, 2);\n" +" assert_eq!(report.blood_pressure_change, Some((-5, -4)));\n" "}\n" "```" msgstr "" -#: src/control-flow/blocks.md:25 -msgid "" -"The same rule is used for functions: the value of the function body is the " -"return value:" -msgstr "" - -#: src/control-flow/blocks.md:28 -msgid "" -"```rust,editable\n" -"fn double(x: i32) -> i32 {\n" -" x + x\n" -"}\n" -"\n" -"fn main() {\n" -" println!(\"doubled: {}\", double(7));\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/blocks.md:38 -msgid "" -"However if the last expression ends with `;`, then the resulting value and " -"type is `()`." -msgstr "" - -#: src/control-flow/blocks.md:43 -msgid "" -"The point of this slide is to show that blocks have a type and value in " -"Rust. " -msgstr "" - -#: src/control-flow/blocks.md:44 -msgid "" -"You can show how the value of the block changes by changing the last line in " -"the block. For instance, adding/removing a semicolon or using a `return`." -msgstr "" - -#: src/control-flow/if-expressions.md:1 -msgid "`if` expressions" -msgstr "" - -#: src/control-flow/if-expressions.md:3 -msgid "" -"You use [`if` expressions](https://doc.rust-lang.org/reference/expressions/" -"if-expr.html#if-expressions) exactly like `if` statements in other languages:" -msgstr "" - -#: src/control-flow/if-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" if x % 2 == 0 {\n" -" x = x / 2;\n" -" } else {\n" -" x = 3 * x + 1;\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/if-expressions.md:18 -msgid "" -"In addition, you can use `if` as an expression. The last expression of each " -"block becomes the value of the `if` expression:" -msgstr "" - -#: src/control-flow/if-expressions.md:22 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/if-expressions.md:35 -msgid "" -"Because `if` is an expression and must have a particular type, both of its " -"branch blocks must have the same type. Consider showing what happens if you " -"add `;` after `x / 2` in the second example." -msgstr "" - -#: src/control-flow/if-let-expressions.md:1 -msgid "`if let` expressions" -msgstr "" - -#: src/control-flow/if-let-expressions.md:3 -msgid "" -"The [`if let` expression](https://doc.rust-lang.org/reference/expressions/if-" -"expr.html#if-let-expressions) lets you execute different code depending on " -"whether a value matches a pattern:" -msgstr "" - -#: src/control-flow/if-let-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let arg = std::env::args().next();\n" -" if let Some(value) = arg {\n" -" println!(\"Program name: {value}\");\n" -" } else {\n" -" println!(\"Missing name?\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/if-let-expressions.md:18 -#: src/control-flow/while-let-expressions.md:21 -#: src/control-flow/match-expressions.md:23 -msgid "" -"See [pattern matching](../pattern-matching.md) for more details on patterns " -"in Rust." -msgstr "" - -#: src/control-flow/if-let-expressions.md:23 -msgid "" -"`if let` can be more concise than `match`, e.g., when only one case is " -"interesting. In contrast, `match` requires all branches to be covered." -msgstr "" - -#: src/control-flow/if-let-expressions.md:24 -msgid "A common usage is handling `Some` values when working with `Option`." -msgstr "" - -#: src/control-flow/if-let-expressions.md:25 -msgid "" -"Unlike `match`, `if let` does not support guard clauses for pattern matching." -msgstr "" - -#: src/control-flow/if-let-expressions.md:26 -msgid "" -"Since 1.65, a similar [let-else](https://doc.rust-lang.org/rust-by-example/" -"flow_control/let_else.html) construct allows to do a destructuring " -"assignment, or if it fails, have a non-returning block branch (panic/return/" -"break/continue):" -msgstr "" - -#: src/control-flow/if-let-expressions.md:28 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" println!(\"{:?}\", second_word_to_upper(\"foo bar\"));\n" -"}\n" -" \n" -"fn second_word_to_upper(s: &str) -> Option {\n" -" let mut it = s.split(' ');\n" -" let (Some(_), Some(item)) = (it.next(), it.next()) else {\n" -" return None;\n" -" };\n" -" Some(item.to_uppercase())\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/while-expressions.md:1 -msgid "`while` loops" -msgstr "" - -#: src/control-flow/while-expressions.md:3 -msgid "" -"The [`while` keyword](https://doc.rust-lang.org/reference/expressions/loop-" -"expr.html#predicate-loops) works very similar to other languages:" -msgstr "" - -#: src/control-flow/while-expressions.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" while x != 1 {\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -" }\n" -" println!(\"Final x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/while-let-expressions.md:1 -msgid "`while let` loops" -msgstr "" - -#: src/control-flow/while-let-expressions.md:3 -msgid "" -"Like with `if let`, there is a [`while let`](https://doc.rust-lang.org/" -"reference/expressions/loop-expr.html#predicate-pattern-loops) variant which " -"repeatedly tests a value against a pattern:" -msgstr "" - -#: src/control-flow/while-let-expressions.md:6 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();\n" -"\n" -" while let Some(x) = iter.next() {\n" -" println!(\"x: {x}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/while-let-expressions.md:17 -msgid "" -"Here the iterator returned by `v.iter()` will return a `Option` on " -"every call to `next()`. It returns `Some(x)` until it is done, after which " -"it will return `None`. The `while let` lets us keep iterating through all " -"items." -msgstr "" - -#: src/control-flow/while-let-expressions.md:26 -msgid "" -"Point out that the `while let` loop will keep going as long as the value " -"matches the pattern." -msgstr "" - -#: src/control-flow/while-let-expressions.md:27 -msgid "" -"You could rewrite the `while let` loop as an infinite loop with an if " -"statement that breaks when there is no value to unwrap for `iter.next()`. " -"The `while let` provides syntactic sugar for the above scenario." -msgstr "" - -#: src/control-flow/for-expressions.md:1 -msgid "`for` loops" -msgstr "" - -#: src/control-flow/for-expressions.md:3 -msgid "" -"The [`for` loop](https://doc.rust-lang.org/std/keyword.for.html) is closely " -"related to the [`while let` loop](while-let-expression.md). It will " -"automatically call `into_iter()` on the expression and then iterate over it:" -msgstr "" - -#: src/control-flow/for-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -"\n" -" for x in v {\n" -" println!(\"x: {x}\");\n" -" }\n" -" \n" -" for i in (0..10).step_by(2) {\n" -" println!(\"i: {i}\");\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/for-expressions.md:21 -msgid "You can use `break` and `continue` here as usual." -msgstr "" - -#: src/control-flow/for-expressions.md:25 -msgid "Index iteration is not a special syntax in Rust for just that case." -msgstr "" - -#: src/control-flow/for-expressions.md:26 -msgid "`(0..10)` is a range that implements an `Iterator` trait. " -msgstr "" - -#: src/control-flow/for-expressions.md:27 -msgid "" -"`step_by` is a method that returns another `Iterator` that skips every other " -"element. " -msgstr "" - -#: src/control-flow/for-expressions.md:28 -msgid "" -"Modify the elements in the vector and explain the compiler errors. Change " -"vector `v` to be mutable and the for loop to `for x in v.iter_mut()`." -msgstr "" - -#: src/control-flow/loop-expressions.md:1 -msgid "`loop` expressions" -msgstr "" - -#: src/control-flow/loop-expressions.md:3 -msgid "" -"Finally, there is a [`loop` keyword](https://doc.rust-lang.org/reference/" -"expressions/loop-expr.html#infinite-loops) which creates an endless loop." -msgstr "" - -#: src/control-flow/loop-expressions.md:6 -msgid "Here you must either `break` or `return` to stop the loop:" -msgstr "" - -#: src/control-flow/loop-expressions.md:8 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let mut x = 10;\n" -" loop {\n" -" x = if x % 2 == 0 {\n" -" x / 2\n" -" } else {\n" -" 3 * x + 1\n" -" };\n" -" if x == 1 {\n" -" break;\n" -" }\n" -" }\n" -" println!(\"Final x: {x}\");\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/loop-expressions.md:27 -msgid "Break the `loop` with a value (e.g. `break 8`) and print it out." -msgstr "" - -#: src/control-flow/loop-expressions.md:28 -msgid "" -"Note that `loop` is the only looping construct which returns a non-trivial " -"value. This is because it's guaranteed to be entered at least once (unlike " -"`while` and `for` loops)." -msgstr "" - -#: src/control-flow/match-expressions.md:1 -msgid "`match` expressions" -msgstr "" - -#: src/control-flow/match-expressions.md:3 -msgid "" -"The [`match` keyword](https://doc.rust-lang.org/reference/expressions/match-" -"expr.html) is used to match a value against one or more patterns. In that " -"sense, it works like a series of `if let` expressions:" -msgstr "" - -#: src/control-flow/match-expressions.md:7 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" match std::env::args().next().as_deref() {\n" -" Some(\"cat\") => println!(\"Will do cat things\"),\n" -" Some(\"ls\") => println!(\"Will ls some files\"),\n" -" Some(\"mv\") => println!(\"Let's move some files\"),\n" -" Some(\"rm\") => println!(\"Uh, dangerous!\"),\n" -" None => println!(\"Hmm, no program name?\"),\n" -" _ => println!(\"Unknown program name!\"),\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/match-expressions.md:20 -msgid "" -"Like `if let`, each match arm must have the same type. The type is the last " -"expression of the block, if any. In the example above, the type is `()`." -msgstr "" - -#: src/control-flow/match-expressions.md:28 -msgid "Save the match expression to a variable and print it out." -msgstr "" - -#: src/control-flow/match-expressions.md:29 -msgid "Remove `.as_deref()` and explain the error." -msgstr "" - -#: src/control-flow/match-expressions.md:30 -msgid "" -"`std::env::args().next()` returns an `Option`, but we cannot match " -"against `String`." -msgstr "" - -#: src/control-flow/match-expressions.md:31 -msgid "" -"`as_deref()` transforms an `Option` to `Option<&T::Target>`. In our case, " -"this turns `Option` into `Option<&str>`." -msgstr "" - -#: src/control-flow/match-expressions.md:32 -msgid "" -"We can now use pattern matching to match against the `&str` inside `Option`." -msgstr "" - -#: src/control-flow/break-continue.md:1 -msgid "`break` and `continue`" -msgstr "" - -#: src/control-flow/break-continue.md:3 -msgid "" -"If you want to exit a loop early, use [`break`](https://doc.rust-lang.org/" -"reference/expressions/loop-expr.html#break-expressions)," -msgstr "" - -#: src/control-flow/break-continue.md:4 -msgid "" -"If you want to immediately start the next iteration use [`continue`](https://" -"doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)." -msgstr "" - -#: src/control-flow/break-continue.md:7 -msgid "" -"Both `continue` and `break` can optionally take a label argument which is " -"used to break out of nested loops:" -msgstr "" - -#: src/control-flow/break-continue.md:10 -msgid "" -"```rust,editable\n" -"fn main() {\n" -" let v = vec![10, 20, 30];\n" -" let mut iter = v.into_iter();\n" -" 'outer: while let Some(x) = iter.next() {\n" -" println!(\"x: {x}\");\n" -" let mut i = 0;\n" -" while i < x {\n" -" println!(\"x: {x}, i: {i}\");\n" -" i += 1;\n" -" if i == 3 {\n" -" break 'outer;\n" -" }\n" -" }\n" -" }\n" -"}\n" -"```" -msgstr "" - -#: src/control-flow/break-continue.md:28 -msgid "" -"In this case we break the outer loop after 3 iterations of the inner loop." -msgstr "" - #: src/std.md:3 msgid "" "Rust comes with a standard library which helps establish a set of common " @@ -7567,6 +7823,14 @@ msgid "" "compiles. Where do you think we might run into issues?" msgstr "" +#: src/std/hashmap.md:64 +msgid "" +"This type has several \"method-specific\" return types, such as `std::" +"collections::hash_map::Keys`. These types often appear in searches of the " +"Rust docs. Show students the docs for this type, and the helpful link back " +"to the `keys` method." +msgstr "" + #: src/std/box.md:1 msgid "`Box`" msgstr "" @@ -7689,9 +7953,9 @@ msgstr "" #: src/std/box-recursive.md:33 msgid "" -"If the `Box` was not used here and we attempted to embed a `List` directly " -"into the `List`, the compiler would not compute a fixed size of the struct " -"in memory, it would look infinite." +"If `Box` was not used and we attempted to embed a `List` directly into the " +"`List`, the compiler would not compute a fixed size of the struct in memory " +"(`List` would be of infinite size)." msgstr "" #: src/std/box-recursive.md:36 @@ -7763,94 +8027,134 @@ msgstr "" #: src/std/rc.md:18 msgid "" -"If you need to mutate the data inside an `Rc`, you will need to wrap the " -"data in a type such as [`Cell` or `RefCell`](../concurrency/shared_state/arc." -"md)." +"See [`Arc`](../concurrency/shared_state/arc.md) and [`Mutex`](https://doc." +"rust-lang.org/std/sync/struct.Mutex.html) if you are in a multi-threaded " +"context." msgstr "" -#: src/std/rc.md:20 -msgid "" -"See [`Arc`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) if you are " -"in a multi-threaded context." -msgstr "" - -#: src/std/rc.md:21 +#: src/std/rc.md:19 msgid "" "You can _downgrade_ a shared pointer into a [`Weak`](https://doc.rust-lang." "org/std/rc/struct.Weak.html) pointer to create cycles that will get dropped." msgstr "" -#: src/std/rc.md:31 +#: src/std/rc.md:29 msgid "" "`Rc`'s count ensures that its contained value is valid for as long as there " "are references." msgstr "" -#: src/std/rc.md:32 -msgid "Like C++'s `std::shared_ptr`." +#: src/std/rc.md:30 +msgid "`Rc` in Rust is like `std::shared_ptr` in C++." msgstr "" -#: src/std/rc.md:33 +#: src/std/rc.md:31 msgid "" "`Rc::clone` is cheap: it creates a pointer to the same allocation and " "increases the reference count. Does not make a deep clone and can generally " "be ignored when looking for performance issues in code." msgstr "" -#: src/std/rc.md:34 +#: src/std/rc.md:32 msgid "" "`make_mut` actually clones the inner value if necessary (\"clone-on-write\") " "and returns a mutable reference." msgstr "" -#: src/std/rc.md:35 +#: src/std/rc.md:33 msgid "Use `Rc::strong_count` to check the reference count." msgstr "" -#: src/std/rc.md:36 -msgid "" -"Compare the different datatypes mentioned. `Box` enables (im)mutable borrows " -"that are enforced at compile time. `RefCell` enables (im)mutable borrows " -"that are enforced at run time and will panic if it fails at runtime." -msgstr "" - -#: src/std/rc.md:37 +#: src/std/rc.md:34 msgid "" "`Rc::downgrade` gives you a _weakly reference-counted_ object to create " -"cycles that will be dropped properly (likely in combination with `RefCell`)." +"cycles that will be dropped properly (likely in combination with `RefCell`, " +"on the next slide)." msgstr "" -#: src/std/rc.md:41 +#: src/std/cell.md:1 +msgid "`Cell` and `RefCell`" +msgstr "" + +#: src/std/cell.md:3 +msgid "" +"[`Cell`](https://doc.rust-lang.org/std/cell/struct.Cell.html) and [`RefCell`]" +"(https://doc.rust-lang.org/std/cell/struct.RefCell.html) implement what Rust " +"calls _interior mutability:_ mutation of values in an immutable context." +msgstr "" + +#: src/std/cell.md:8 +msgid "" +"`Cell` is typically used for simple types, as it requires copying or moving " +"values. More complex interior types typically use `RefCell`, which tracks " +"shared and exclusive references at runtime and panics if they are misused." +msgstr "" + +#: src/std/cell.md:12 msgid "" "```rust,editable\n" -"use std::rc::{Rc, Weak};\n" "use std::cell::RefCell;\n" +"use std::rc::Rc;\n" "\n" -"#[derive(Debug)]\n" +"#[derive(Debug, Default)]\n" "struct Node {\n" " value: i64,\n" -" parent: Option>>,\n" " children: Vec>>,\n" "}\n" "\n" +"impl Node {\n" +" fn new(value: i64) -> Rc> {\n" +" Rc::new(RefCell::new(Node { value, ..Node::default() }))\n" +" }\n" +"\n" +" fn sum(&self) -> i64 {\n" +" self.value + self.children.iter().map(|c| c.borrow().sum()).sum::" +"()\n" +" }\n" +"}\n" +"\n" "fn main() {\n" -" let mut root = Rc::new(RefCell::new(Node {\n" -" value: 42,\n" -" parent: None,\n" -" children: vec![],\n" -" }));\n" -" let child = Rc::new(RefCell::new(Node {\n" -" value: 43,\n" -" children: vec![],\n" -" parent: Some(Rc::downgrade(&root))\n" -" }));\n" -" root.borrow_mut().children.push(child);\n" +" let root = Node::new(1);\n" +" root.borrow_mut().children.push(Node::new(5));\n" +" let subtree = Node::new(10);\n" +" subtree.borrow_mut().children.push(Node::new(11));\n" +" subtree.borrow_mut().children.push(Node::new(12));\n" +" root.borrow_mut().children.push(subtree);\n" "\n" " println!(\"graph: {root:#?}\");\n" +" println!(\"graph sum: {}\", root.borrow().sum());\n" "}\n" "```" msgstr "" +#: src/std/cell.md:47 +msgid "" +"If we were using `Cell` instead of `RefCell` in this example, we would have " +"to move the `Node` out of the `Rc` to push children, then move it back in. " +"This is safe because there's always one, un-referenced value in the cell, " +"but it's not ergonomic." +msgstr "" + +#: src/std/cell.md:48 +msgid "" +"To do anything with a Node, you must call a `RefCell` method, usually " +"`borrow` or `borrow_mut`." +msgstr "" + +#: src/std/cell.md:49 +msgid "" +"Demonstrate that reference loops can be created by adding `root` to `subtree." +"children` (don't try to print it!)." +msgstr "" + +#: src/std/cell.md:50 +msgid "" +"To demonstrate a runtime panic, add a `fn inc(&mut self)` that increments " +"`self.value` and calls the same method on its children. This will panic in " +"the presence of the reference loop, with `thread 'main' panicked at 'already " +"borrowed: BorrowMutError'`." +msgstr "" + #: src/modules.md:3 msgid "We have seen how `impl` blocks let us namespace functions to a type." msgstr "" @@ -8018,7 +8322,8 @@ msgid "" msgstr "" #: src/modules/filesystem.md:3 -msgid "The module content can be omitted:" +msgid "" +"Omitting the module content will tell Rust to look for it in another file:" msgstr "" #: src/modules/filesystem.md:5 @@ -8029,49 +8334,32 @@ msgid "" msgstr "" #: src/modules/filesystem.md:9 -msgid "The `garden` module content is found at:" -msgstr "" - -#: src/modules/filesystem.md:11 -msgid "`src/garden.rs` (modern Rust 2018 style)" +msgid "" +"This tells rust that the `garden` module content is found at `src/garden." +"rs`. Similarly, a `garden::vegetables` module can be found at `src/garden/" +"vegetables.rs`." msgstr "" #: src/modules/filesystem.md:12 -msgid "`src/garden/mod.rs` (older Rust 2015 style)" -msgstr "" - -#: src/modules/filesystem.md:14 -msgid "Similarly, a `garden::vegetables` module can be found at:" -msgstr "" - -#: src/modules/filesystem.md:16 -msgid "`src/garden/vegetables.rs` (modern Rust 2018 style)" -msgstr "" - -#: src/modules/filesystem.md:17 -msgid "`src/garden/vegetables/mod.rs` (older Rust 2015 style)" -msgstr "" - -#: src/modules/filesystem.md:19 msgid "The `crate` root is in:" msgstr "" -#: src/modules/filesystem.md:21 +#: src/modules/filesystem.md:14 msgid "`src/lib.rs` (for a library crate)" msgstr "" -#: src/modules/filesystem.md:22 +#: src/modules/filesystem.md:15 msgid "`src/main.rs` (for a binary crate)" msgstr "" -#: src/modules/filesystem.md:24 +#: src/modules/filesystem.md:17 msgid "" "Modules defined in files can be documented, too, using \"inner doc " "comments\". These document the item that contains them -- in this case, a " "module." msgstr "" -#: src/modules/filesystem.md:27 +#: src/modules/filesystem.md:20 msgid "" "```rust,editable,compile_fail\n" "//! This module implements the garden, including a highly performant " @@ -8090,17 +8378,23 @@ msgid "" "```" msgstr "" -#: src/modules/filesystem.md:44 +#: src/modules/filesystem.md:37 msgid "" -"The change from `module/mod.rs` to `module.rs` doesn't preclude the use of " -"submodules in Rust 2018. (It was mandatory in Rust 2015.)" +"Before Rust 2018, modules needed to be located at `module/mod.rs` instead of " +"`module.rs`, and this is still a working alternative for editions after 2018." msgstr "" -#: src/modules/filesystem.md:47 -msgid "The following is valid:" +#: src/modules/filesystem.md:39 +msgid "" +"The main reason to introduce `filename.rs` as alternative to `filename/mod." +"rs` was because many files named `mod.rs` can be hard to distinguish in IDEs." msgstr "" -#: src/modules/filesystem.md:49 +#: src/modules/filesystem.md:42 +msgid "Deeper nesting can use folders, even if the main module is a file:" +msgstr "" + +#: src/modules/filesystem.md:44 msgid "" "```ignore\n" "src/\n" @@ -8111,129 +8405,26 @@ msgid "" "```" msgstr "" -#: src/modules/filesystem.md:57 +#: src/modules/filesystem.md:52 msgid "" -"The main reason for the change is to prevent many files named `mod.rs`, " -"which can be hard to distinguish in IDEs." +"The place rust will look for modules can be changed with a compiler " +"directive:" msgstr "" -#: src/modules/filesystem.md:60 -msgid "" -"Rust will look for modules in `modulename/mod.rs` and `modulename.rs`, but " -"this can be changed with a compiler directive:" -msgstr "" - -#: src/modules/filesystem.md:63 +#: src/modules/filesystem.md:54 msgid "" "```rust,ignore\n" "#[path = \"some/path.rs\"]\n" -"mod some_module { }\n" +"mod some_module;\n" "```" msgstr "" -#: src/modules/filesystem.md:68 +#: src/modules/filesystem.md:59 msgid "" "This is useful, for example, if you would like to place tests for a module " "in a file named `some_module_test.rs`, similar to the convention in Go." msgstr "" -#: src/exercises/day-2/afternoon.md:1 -msgid "Day 2: Afternoon Exercises" -msgstr "" - -#: src/exercises/day-2/afternoon.md:3 -msgid "The exercises for this afternoon will focus on strings and iterators." -msgstr "" - -#: src/exercises/day-2/luhn.md:3 -msgid "" -"The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is used " -"to validate credit card numbers. The algorithm takes a string as input and " -"does the following to validate the credit card number:" -msgstr "" - -#: src/exercises/day-2/luhn.md:7 -msgid "Ignore all spaces. Reject number with less than two digits." -msgstr "" - -#: src/exercises/day-2/luhn.md:9 -msgid "" -"Moving from right to left, double every second digit: for the number `1234`, " -"we double `3` and `1`." -msgstr "" - -#: src/exercises/day-2/luhn.md:12 -msgid "" -"After doubling a digit, sum the digits. So doubling `7` becomes `14` which " -"becomes `5`." -msgstr "" - -#: src/exercises/day-2/luhn.md:15 -msgid "Sum all the undoubled and doubled digits." -msgstr "" - -#: src/exercises/day-2/luhn.md:17 -msgid "The credit card number is valid if the sum ends with `0`." -msgstr "" - -#: src/exercises/day-2/luhn.md:19 -msgid "" -"Copy the following code to and implement the " -"function:" -msgstr "" - -#: src/exercises/day-2/luhn.md:23 -msgid "" -"```rust\n" -"// TODO: remove this when you're done with your implementation.\n" -"#![allow(unused_variables, dead_code)]\n" -"\n" -"pub fn luhn(cc_number: &str) -> bool {\n" -" unimplemented!()\n" -"}\n" -"\n" -"#[test]\n" -"fn test_non_digit_cc_number() {\n" -" assert!(!luhn(\"foo\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_empty_cc_number() {\n" -" assert!(!luhn(\"\"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_single_digit_cc_number() {\n" -" assert!(!luhn(\"0\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_two_digit_cc_number() {\n" -" assert!(luhn(\" 0 0 \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_valid_cc_number() {\n" -" assert!(luhn(\"4263 9826 4026 9299\"));\n" -" assert!(luhn(\"4539 3195 0343 6467\"));\n" -" assert!(luhn(\"7992 7398 713\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_invalid_cc_number() {\n" -" assert!(!luhn(\"4223 9826 4026 9299\"));\n" -" assert!(!luhn(\"4539 3195 0343 6476\"));\n" -" assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}\n" -"\n" -"#[allow(dead_code)]\n" -"fn main() {}\n" -"```" -msgstr "" - #: src/exercises/day-2/strings-iterators.md:3 msgid "" "In this exercise, you are implementing a routing component of a web server. " @@ -8333,8 +8524,8 @@ msgstr "" #: src/generics.md:3 msgid "" -"Rust support generics, which lets you abstract an algorithm (such as " -"sorting) over the types used in the algorithm." +"Rust support generics, which lets you abstract algorithms or data structures " +"(such as sorting or a binary tree) over the types used or stored." msgstr "" #: src/generics/data-types.md:3 @@ -8643,10 +8834,16 @@ msgid "" msgstr "" #: src/traits/deriving-traits.md:3 -msgid "You can let the compiler derive a number of traits:" +msgid "" +"Rust derive macros work by automatically generating code that implements the " +"specified traits for a data structure." msgstr "" #: src/traits/deriving-traits.md:5 +msgid "You can let the compiler derive a number of traits as follows:" +msgstr "" + +#: src/traits/deriving-traits.md:7 msgid "" "```rust,editable\n" "#[derive(Debug, Clone, PartialEq, Eq, Default)]\n" @@ -8673,9 +8870,9 @@ msgstr "" msgid "" "```rust,editable\n" "trait Equals {\n" -" fn equal(&self, other: &Self) -> bool;\n" -" fn not_equal(&self, other: &Self) -> bool {\n" -" !self.equal(other)\n" +" fn equals(&self, other: &Self) -> bool;\n" +" fn not_equals(&self, other: &Self) -> bool {\n" +" !self.equals(other)\n" " }\n" "}\n" "\n" @@ -8683,7 +8880,7 @@ msgid "" "struct Centimeter(i16);\n" "\n" "impl Equals for Centimeter {\n" -" fn equal(&self, other: &Centimeter) -> bool {\n" +" fn equals(&self, other: &Centimeter) -> bool {\n" " self.0 == other.0\n" " }\n" "}\n" @@ -8691,8 +8888,8 @@ msgid "" "fn main() {\n" " let a = Centimeter(10);\n" " let b = Centimeter(20);\n" -" println!(\"{a:?} equals {b:?}: {}\", a.equal(&b));\n" -" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equal(&b));\n" +" println!(\"{a:?} equals {b:?}: {}\", a.equals(&b));\n" +" println!(\"{a:?} not_equals {b:?}: {}\", a.not_equals(&b));\n" "}\n" "```" msgstr "" @@ -8705,38 +8902,38 @@ msgid "" msgstr "" #: src/traits/default-methods.md:35 -msgid "Move method `not_equal` to a new trait `NotEqual`." +msgid "Move method `not_equals` to a new trait `NotEquals`." msgstr "" #: src/traits/default-methods.md:37 -msgid "Make `NotEqual` a super trait for `Equal`." +msgid "Make `Equals` a super trait for `NotEquals`." msgstr "" #: src/traits/default-methods.md:38 msgid "" "```rust,editable,compile_fail\n" -"trait NotEqual: Equals {\n" -" fn not_equal(&self, other: &Self) -> bool {\n" -" !self.equal(other)\n" +"trait NotEquals: Equals {\n" +" fn not_equals(&self, other: &Self) -> bool {\n" +" !self.equals(other)\n" " }\n" "}\n" "```" msgstr "" #: src/traits/default-methods.md:46 -msgid "Provide a blanket implementation of `NotEqual` for `Equal`." +msgid "Provide a blanket implementation of `NotEquals` for `Equals`." msgstr "" #: src/traits/default-methods.md:47 msgid "" "```rust,editable,compile_fail\n" -"trait NotEqual {\n" -" fn not_equal(&self, other: &Self) -> bool;\n" +"trait NotEquals {\n" +" fn not_equals(&self, other: &Self) -> bool;\n" "}\n" "\n" -"impl NotEqual for T where T: Equals {\n" -" fn not_equal(&self, other: &Self) -> bool {\n" -" !self.equal(other)\n" +"impl NotEquals for T where T: Equals {\n" +" fn not_equals(&self, other: &Self) -> bool {\n" +" !self.equals(other)\n" " }\n" "}\n" "```" @@ -8744,8 +8941,8 @@ msgstr "" #: src/traits/default-methods.md:58 msgid "" -"With the blanket implementation, you no longer need `NotEqual` as a super " -"trait for `Equal`." +"With the blanket implementation, you no longer need `Equals` as a super " +"trait for `NotEqual`." msgstr "" #: src/traits/trait-bounds.md:3 @@ -9198,7 +9395,7 @@ msgstr "" #: src/traits/default.md:3 msgid "" "[`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) trait " -"provides a default implementation of a trait." +"produces a default value for a type." msgstr "" #: src/traits/default.md:5 @@ -9221,12 +9418,12 @@ msgid "" "}\n" "\n" "fn main() {\n" -" let default_struct: Derived = Default::default();\n" +" let default_struct = Derived::default();\n" " println!(\"{default_struct:#?}\");\n" "\n" " let almost_default_struct = Derived {\n" " y: \"Y is set!\".into(),\n" -" ..Default::default()\n" +" ..Derived::default()\n" " };\n" " println!(\"{almost_default_struct:#?}\");\n" "\n" @@ -9244,7 +9441,7 @@ msgstr "" #: src/traits/default.md:41 msgid "" -"Derived implementation will produce an instance where all fields are set to " +"A derived implementation will produce a value where all fields are set to " "their default values." msgstr "" @@ -9268,6 +9465,13 @@ msgid "" "provides convenience methods that use it." msgstr "" +#: src/traits/default.md:46 +msgid "" +"the `..` syntax is called [struct update syntax](https://doc.rust-lang.org/" +"book/ch05-01-defining-structs.html#creating-instances-from-other-instances-" +"with-struct-update-syntax)" +msgstr "" + #: src/traits/operators.md:1 msgid "`Add`, `Mul`, ..." msgstr "" @@ -9313,13 +9517,22 @@ msgid "" msgstr "" #: src/traits/operators.md:33 -msgid "Why is `Output` an associated type? Could it be made a type parameter?" +msgid "" +"Why is `Output` an associated type? Could it be made a type parameter of the " +"method?" msgstr "" #: src/traits/operators.md:34 msgid "" -"Short answer: Type parameters are controlled by the caller, but associated " -"types (like `Output`) are controlled by the implementor of a trait." +"Short answer: Function type parameters are controlled by the caller, but " +"associated types (like `Output`) are controlled by the implementor of a " +"trait." +msgstr "" + +#: src/traits/operators.md:37 +msgid "" +"You could implement `Add` for two different types, e.g. `impl Add<(i32, " +"i32)> for Point` would add a tuple to a `Point`." msgstr "" #: src/traits/closures.md:1 @@ -9344,41 +9557,73 @@ msgid "" "\n" "fn main() {\n" " let add_3 = |x| x + 3;\n" -" let mul_5 = |x| x * 5;\n" -"\n" " println!(\"add_3: {}\", apply_with_log(add_3, 10));\n" -" println!(\"mul_5: {}\", apply_with_log(mul_5, 20));\n" +" println!(\"add_3: {}\", apply_with_log(add_3, 20));\n" +"\n" +" let mut v = Vec::new();\n" +" let mut accumulate = |x: i32| {\n" +" v.push(x);\n" +" v.iter().sum::()\n" +" };\n" +" println!(\"accumulate: {}\", apply_with_log(&mut accumulate, 4));\n" +" println!(\"accumulate: {}\", apply_with_log(&mut accumulate, 5));\n" +"\n" +" let multiply_sum = |x| x * v.into_iter().sum::();\n" +" println!(\"multiply_sum: {}\", apply_with_log(multiply_sum, 3));\n" "}\n" "```" msgstr "" -#: src/traits/closures.md:25 +#: src/traits/closures.md:34 msgid "" -"If you have an `FnOnce`, you may only call it once. It might consume " -"captured values." +"An `Fn` (e.g. `add_3`) neither consumes nor mutates captured values, or " +"perhaps captures nothing at all. It can be called multiple times " +"concurrently." msgstr "" -#: src/traits/closures.md:27 +#: src/traits/closures.md:37 msgid "" -"An `FnMut` might mutate captured values, so you can call it multiple times " -"but not concurrently." +"An `FnMut` (e.g. `accumulate`) might mutate captured values. You can call it " +"multiple times, but not concurrently." msgstr "" -#: src/traits/closures.md:29 +#: src/traits/closures.md:40 msgid "" -"An `Fn` neither consumes nor mutates captured values, or perhaps captures " -"nothing at all, so it can be called multiple times concurrently." +"If you have an `FnOnce` (e.g. `multiply_sum`), you may only call it once. It " +"might consume captured values." msgstr "" -#: src/traits/closures.md:32 +#: src/traits/closures.md:43 msgid "" "`FnMut` is a subtype of `FnOnce`. `Fn` is a subtype of `FnMut` and `FnOnce`. " "I.e. you can use an `FnMut` wherever an `FnOnce` is called for, and you can " "use an `Fn` wherever an `FnMut` or `FnOnce` is called for." msgstr "" -#: src/traits/closures.md:36 -msgid "`move` closures only implement `FnOnce`." +#: src/traits/closures.md:47 +msgid "" +"The compiler also infers `Copy` (e.g. for `add_3`) and `Clone` (e.g. " +"`multiply_sum`), depending on what the closure captures." +msgstr "" + +#: src/traits/closures.md:50 +msgid "" +"By default, closures will capture by reference if they can. The `move` " +"keyword makes them capture by value." +msgstr "" + +#: src/traits/closures.md:52 +msgid "" +"```rust,editable\n" +"fn make_greeter(prefix: String) -> impl Fn(&str) {\n" +" return move |name| println!(\"{} {}\", prefix, name)\n" +"}\n" +"\n" +"fn main() {\n" +" let hi = make_greeter(\"Hi\".to_string());\n" +" hi(\"there\");\n" +"}\n" +"```" msgstr "" #: src/exercises/day-3/morning.md:1 @@ -9386,7 +9631,13 @@ msgid "Day 3: Morning Exercises" msgstr "" #: src/exercises/day-3/morning.md:3 -msgid "We will design a classical GUI library traits and trait objects." +msgid "We will design a classical GUI library using traits and trait objects." +msgstr "" + +#: src/exercises/day-3/morning.md:5 +msgid "" +"We will also look at enum dispatch with an exercise involving points and " +"polygons." msgstr "" #: src/exercises/day-3/simple-gui.md:3 @@ -9595,6 +9846,151 @@ msgid "" "```" msgstr "" +#: src/exercises/day-3/points-polygons.md:1 +msgid "Polygon Struct" +msgstr "" + +#: src/exercises/day-3/points-polygons.md:3 +msgid "" +"We will create a `Polygon` struct which contain some points. Copy the code " +"below to and fill in the missing methods to " +"make the tests pass:" +msgstr "" + +#: src/exercises/day-3/points-polygons.md:7 +msgid "" +"```rust\n" +"// TODO: remove this when you're done with your implementation.\n" +"#![allow(unused_variables, dead_code)]\n" +"\n" +"pub struct Point {\n" +" // add fields\n" +"}\n" +"\n" +"impl Point {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Polygon {\n" +" // add fields\n" +"}\n" +"\n" +"impl Polygon {\n" +" // add methods\n" +"}\n" +"\n" +"pub struct Circle {\n" +" // add fields\n" +"}\n" +"\n" +"impl Circle {\n" +" // add methods\n" +"}\n" +"\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"\n" +"#[allow(dead_code)]\n" +"fn main() {}\n" +"```" +msgstr "" + +#: src/exercises/day-3/points-polygons.md:117 +msgid "" +"Since the method signatures are missing from the problem statements, the key " +"part of the exercise is to specify those correctly. You don't have to modify " +"the tests." +msgstr "" + +#: src/exercises/day-3/points-polygons.md:120 +msgid "Other interesting parts of the exercise:" +msgstr "" + +#: src/exercises/day-3/points-polygons.md:122 +msgid "" +"Derive a `Copy` trait for some structs, as in tests the methods sometimes " +"don't borrow their arguments." +msgstr "" + +#: src/exercises/day-3/points-polygons.md:123 +msgid "" +"Discover that `Add` trait must be implemented for two objects to be addable " +"via \"+\". Note that we do not discuss generics until Day 3." +msgstr "" + #: src/error-handling.md:3 msgid "Error handling in Rust is done using explicit control flow:" msgstr "" @@ -9649,25 +10045,27 @@ msgid "" "```rust,editable\n" "use std::panic;\n" "\n" -"let result = panic::catch_unwind(|| {\n" -" println!(\"hello!\");\n" -"});\n" -"assert!(result.is_ok());\n" -"\n" -"let result = panic::catch_unwind(|| {\n" -" panic!(\"oh no!\");\n" -"});\n" -"assert!(result.is_err());\n" +"fn main() {\n" +" let result = panic::catch_unwind(|| {\n" +" println!(\"hello!\");\n" +" });\n" +" assert!(result.is_ok());\n" +" \n" +" let result = panic::catch_unwind(|| {\n" +" panic!(\"oh no!\");\n" +" });\n" +" assert!(result.is_err());\n" +"}\n" "```" msgstr "" -#: src/error-handling/panic-unwind.md:19 +#: src/error-handling/panic-unwind.md:21 msgid "" "This can be useful in servers which should keep running even if a single " "request crashes." msgstr "" -#: src/error-handling/panic-unwind.md:21 +#: src/error-handling/panic-unwind.md:23 msgid "This does not work if `panic = 'abort'` is set in your `Cargo.toml`." msgstr "" @@ -9684,11 +10082,11 @@ msgstr "" #: src/error-handling/result.md:6 msgid "" "```rust,editable\n" -"use std::fs::File;\n" +"use std::fs;\n" "use std::io::Read;\n" "\n" "fn main() {\n" -" let file = File::open(\"diary.txt\");\n" +" let file = fs::File::open(\"diary.txt\");\n" " match file {\n" " Ok(mut file) => {\n" " let mut contents = String::new();\n" @@ -9750,14 +10148,14 @@ msgid "" msgstr "" #: src/error-handling/try-operator.md:19 -msgid "We can use this to simplify our error handing code:" +msgid "We can use this to simplify our error handling code:" msgstr "" #: src/error-handling/try-operator.md:21 msgid "" "```rust,editable\n" -"use std::fs;\n" -"use std::io::{self, Read};\n" +"use std::{fs, io};\n" +"use std::io::Read;\n" "\n" "fn read_username(path: &str) -> Result {\n" " let username_file_result = fs::File::open(path);\n" @@ -9793,6 +10191,24 @@ msgid "" "file, file with username." msgstr "" +#: src/error-handling/try-operator.md:52 +msgid "" +"The return type of the function has to be compatible with the nested " +"functions it calls. For instance, a function returning a `Result` " +"can only apply the `?` operator on a function returning a `Result`. It cannot apply the `?` operator on a function returning an " +"`Option` or `Result` unless `OtherErr` implements " +"`From`. Reciprocally, a function returning an `Option` can only " +"apply the `?` operator on a function returning an `Option`." +msgstr "" + +#: src/error-handling/try-operator.md:57 +msgid "" +"You can convert incompatible types into one another with the different " +"`Option` and `Result` methods such as `Option::ok_or`, `Result::ok`, " +"`Result::err`." +msgstr "" + #: src/error-handling/converting-error-types.md:3 msgid "" "The effective expansion of `?` is a little more complicated than previously " @@ -9877,11 +10293,17 @@ msgstr "" #: src/error-handling/converting-error-types-example.md:55 msgid "" -"It is good practice for all error types to implement `std::error::Error`, " -"which requires `Debug` and `Display`. It's generally helpful for them to " -"implement `Clone` and `Eq` too where possible, to make life easier for tests " -"and consumers of your library. In this case we can't easily do so, because " -"`io::Error` doesn't implement them." +"It is good practice for all error types that don't need to be `no_std` to " +"implement `std::error::Error`, which requires `Debug` and `Display`. The " +"`Error` crate for `core` is only available in [nightly](https://github.com/" +"rust-lang/rust/issues/103765), so not fully `no_std` compatible yet." +msgstr "" + +#: src/error-handling/converting-error-types-example.md:57 +msgid "" +"It's generally helpful for them to implement `Clone` and `Eq` too where " +"possible, to make life easier for tests and consumers of your library. In " +"this case we can't easily do so, because `io::Error` doesn't implement them." msgstr "" #: src/error-handling/deriving-error-enums.md:3 @@ -9906,7 +10328,7 @@ msgid "" "}\n" "\n" "fn read_username(path: &str) -> Result {\n" -" let mut username = String::with_capacity(100);\n" +" let mut username = String::new();\n" " fs::File::open(path)?.read_to_string(&mut username)?;\n" " if username.is_empty() {\n" " return Err(ReadUsernameError::EmptyUsername(String::from(path)));\n" @@ -9945,7 +10367,7 @@ msgstr "" #: src/error-handling/dynamic-errors.md:6 msgid "" "```rust,editable,compile_fail\n" -"use std::fs::{self, File};\n" +"use std::fs;\n" "use std::io::Read;\n" "use thiserror::Error;\n" "use std::error::Error;\n" @@ -9955,8 +10377,8 @@ msgid "" "struct EmptyUsernameError(String);\n" "\n" "fn read_username(path: &str) -> Result> {\n" -" let mut username = String::with_capacity(100);\n" -" File::open(path)?.read_to_string(&mut username)?;\n" +" let mut username = String::new();\n" +" fs::File::open(path)?.read_to_string(&mut username)?;\n" " if username.is_empty() {\n" " return Err(EmptyUsernameError(String::from(path)).into());\n" " }\n" @@ -10606,7 +11028,19 @@ msgstr "" msgid "Let us build a safe wrapper for reading directory content!" msgstr "" -#: src/exercises/day-3/afternoon.md:7 +#: src/exercises/day-3/afternoon.md:5 +msgid "" +"For this exercise, we suggest using a local dev environment instead of the " +"Playground. This will allow you to run your binary on your own machine." +msgstr "" + +#: src/exercises/day-3/afternoon.md:8 +msgid "" +"To get started, follow the [running locally](../../cargo/running-locally.md) " +"instructions." +msgstr "" + +#: src/exercises/day-3/afternoon.md:14 msgid "" "After looking at the exercise, you can look at the [solution](solutions-" "afternoon.md) provided." @@ -10751,7 +11185,7 @@ msgid "" "mod ffi {\n" " use std::os::raw::{c_char, c_int};\n" " #[cfg(not(target_os = \"macos\"))]\n" -" use std::os::raw::{c_long, c_ulong, c_ushort};\n" +" use std::os::raw::{c_long, c_ulong, c_ushort, c_uchar};\n" "\n" " // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" " #[repr(C)]\n" @@ -10761,23 +11195,25 @@ msgid "" "PhantomPinned)>,\n" " }\n" "\n" -" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-" -"gnu.\n" +" // Layout according to the Linux man page for readdir(3), where ino_t " +"and\n" +" // off_t are resolved according to the definitions in\n" +" // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}.\n" " #[cfg(not(target_os = \"macos\"))]\n" " #[repr(C)]\n" " pub struct dirent {\n" -" pub d_ino: c_long,\n" -" pub d_off: c_ulong,\n" +" pub d_ino: c_ulong,\n" +" pub d_off: c_long,\n" " pub d_reclen: c_ushort,\n" -" pub d_type: c_char,\n" +" pub d_type: c_uchar,\n" " pub d_name: [c_char; 256],\n" " }\n" "\n" -" // Layout as per man entry for dirent\n" -" #[cfg(target_os = \"macos\")]\n" +" // Layout according to the macOS man page for dir(5).\n" +" #[cfg(all(target_os = \"macos\"))]\n" " #[repr(C)]\n" " pub struct dirent {\n" -" pub d_ino: u64,\n" +" pub d_fileno: u64,\n" " pub d_seekoff: u64,\n" " pub d_reclen: u16,\n" " pub d_namlen: u16,\n" @@ -10787,7 +11223,22 @@ msgid "" "\n" " extern \"C\" {\n" " pub fn opendir(s: *const c_char) -> *mut DIR;\n" +"\n" +" #[cfg(not(all(target_os = \"macos\", target_arch = \"x86_64\")))]\n" " pub fn readdir(s: *mut DIR) -> *const dirent;\n" +"\n" +" // See https://github.com/rust-lang/libc/issues/414 and the section " +"on\n" +" // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).\n" +" //\n" +" // \"Platforms that existed before these updates were available\" " +"refers\n" +" // to macOS (as opposed to iOS / wearOS / etc.) on Intel and " +"PowerPC.\n" +" #[cfg(all(target_os = \"macos\", target_arch = \"x86_64\"))]\n" +" #[link_name = \"readdir$INODE64\"]\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +"\n" " pub fn closedir(s: *mut DIR) -> c_int;\n" " }\n" "}\n" @@ -10860,9 +11311,9 @@ msgstr "" #: src/android/setup.md:6 msgid "" "```shell\n" -"$ source build/envsetup.sh\n" -"$ lunch aosp_cf_x86_64_phone-userdebug\n" -"$ acloud create\n" +"source build/envsetup.sh\n" +"lunch aosp_cf_x86_64_phone-userdebug\n" +"acloud create\n" "```" msgstr "" @@ -11008,9 +11459,15 @@ msgstr "" #: src/android/build-rules/binary.md:29 msgid "" "```shell\n" -"$ m hello_rust\n" -"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\"\n" -"$ adb shell /data/local/tmp/hello_rust\n" +"m hello_rust\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust /data/local/tmp\"\n" +"adb shell /data/local/tmp/hello_rust\n" +"```" +msgstr "" + +#: src/android/build-rules/binary.md:35 +msgid "" +"```text\n" "Hello from Rust!\n" "```" msgstr "" @@ -11098,10 +11555,16 @@ msgstr "" #: src/android/build-rules/library.md:61 msgid "" "```shell\n" -"$ m hello_rust_with_dep\n" -"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/" +"m hello_rust_with_dep\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_with_dep /data/local/" "tmp\"\n" -"$ adb shell /data/local/tmp/hello_rust_with_dep\n" +"adb shell /data/local/tmp/hello_rust_with_dep\n" +"```" +msgstr "" + +#: src/android/build-rules/library.md:67 +msgid "" +"```text\n" "Hello Bob, it is very\n" "nice to meet you!\n" "```" @@ -11292,10 +11755,10 @@ msgstr "" #: src/android/aidl/deploy.md:5 msgid "" "```shell\n" -"$ m birthday_server\n" -"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/" +"m birthday_server\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_server /data/local/" "tmp\"\n" -"$ adb shell /data/local/tmp/birthday_server\n" +"adb shell /data/local/tmp/birthday_server\n" "```" msgstr "" @@ -11306,19 +11769,31 @@ msgstr "" #: src/android/aidl/deploy.md:13 msgid "" "```shell\n" -"$ adb shell service check birthdayservice\n" +"adb shell service check birthdayservice\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:17 +msgid "" +"```text\n" "Service birthdayservice: found\n" "```" msgstr "" -#: src/android/aidl/deploy.md:18 +#: src/android/aidl/deploy.md:21 msgid "You can also call the service with `service call`:" msgstr "" -#: src/android/aidl/deploy.md:20 +#: src/android/aidl/deploy.md:23 msgid "" "```shell\n" -"$ $ adb shell service call birthdayservice 1 s16 Bob i32 24\n" +"adb shell service call birthdayservice 1 s16 Bob i32 24\n" +"```" +msgstr "" + +#: src/android/aidl/deploy.md:27 +msgid "" +"```text\n" "Result: Parcel(\n" " 0x00000000: 00000000 00000036 00610048 00700070 '....6...H.a.p.p.'\n" " 0x00000010: 00200079 00690042 00740072 00640068 'y. .B.i.r.t.h.d.'\n" @@ -11406,10 +11881,16 @@ msgstr "" #: src/android/aidl/client.md:56 msgid "" "```shell\n" -"$ m birthday_client\n" -"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/" +"m birthday_client\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/birthday_client /data/local/" "tmp\"\n" -"$ adb shell /data/local/tmp/birthday_client Charlie 60\n" +"adb shell /data/local/tmp/birthday_client Charlie 60\n" +"```" +msgstr "" + +#: src/android/aidl/client.md:62 +msgid "" +"```text\n" "Happy Birthday Charlie, congratulations with the 60 years!\n" "```" msgstr "" @@ -11493,10 +11974,10 @@ msgstr "" #: src/android/logging.md:44 msgid "" "```shell\n" -"$ m hello_rust_logs\n" -"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/" +"m hello_rust_logs\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/hello_rust_logs /data/local/" "tmp\"\n" -"$ adb shell /data/local/tmp/hello_rust_logs\n" +"adb shell /data/local/tmp/hello_rust_logs\n" "```" msgstr "" @@ -11507,7 +11988,13 @@ msgstr "" #: src/android/logging.md:52 msgid "" "```shell\n" -"$ adb logcat -s rust\n" +"adb logcat -s rust\n" +"```" +msgstr "" + +#: src/android/logging.md:56 +msgid "" +"```text\n" "09-08 08:38:32.454 2420 2420 D rust: hello_rust_logs: Starting program.\n" "09-08 08:38:32.454 2420 2420 I rust: hello_rust_logs: Things are going " "fine.\n" @@ -11727,10 +12214,10 @@ msgstr "" #: src/android/interoperability/with-c/bindgen.md:100 msgid "" "```shell\n" -"$ m print_birthday_card\n" -"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/" +"m print_birthday_card\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/print_birthday_card /data/local/" "tmp\"\n" -"$ adb shell /data/local/tmp/print_birthday_card\n" +"adb shell /data/local/tmp/print_birthday_card\n" "```" msgstr "" @@ -11756,7 +12243,7 @@ msgstr "" #: src/android/interoperability/with-c/bindgen.md:122 msgid "" "```shell\n" -"$ atest libbirthday_bindgen_test\n" +"atest libbirthday_bindgen_test\n" "```" msgstr "" @@ -11865,10 +12352,10 @@ msgstr "" #: src/android/interoperability/with-c/rust.md:75 msgid "" "```shell\n" -"$ m analyze_numbers\n" -"$ adb push \"$ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/" +"m analyze_numbers\n" +"adb push \"$ANDROID_PRODUCT_OUT/system/bin/analyze_numbers /data/local/" "tmp\"\n" -"$ adb shell /data/local/tmp/analyze_numbers\n" +"adb shell /data/local/tmp/analyze_numbers\n" "```" msgstr "" @@ -11895,6 +12382,42 @@ msgid "" "using this." msgstr "" +#: src/android/interoperability/cpp.md:14 +msgid "" +"At this point, the instructor should switch to the [CXX tutorial](https://" +"cxx.rs/tutorial.html)." +msgstr "" + +#: src/android/interoperability/cpp.md:16 +msgid "Walk the students through the tutorial step by step." +msgstr "" + +#: src/android/interoperability/cpp.md:18 +msgid "" +"Highlight how CXX presents a clean interface without unsafe code in _both " +"languages_." +msgstr "" + +#: src/android/interoperability/cpp.md:20 +msgid "" +"Show the correspondence between [Rust and C++ types](https://cxx.rs/bindings." +"html):" +msgstr "" + +#: src/android/interoperability/cpp.md:22 +msgid "" +"Explain how a Rust `String` cannot map to a C++ `std::string` (the latter " +"does not uphold the UTF-8 invariant). Show that despite being different " +"types, `rust::String` in C++ can be easily constructed from a C++ `std::" +"string`, making it very ergonomic to use." +msgstr "" + +#: src/android/interoperability/cpp.md:28 +msgid "" +"Explain that a Rust function returning `Result` becomes a function " +"which throws a `E` exception in C++ (and vice versa)." +msgstr "" + #: src/android/interoperability/java.md:1 msgid "Interoperability with Java" msgstr "" @@ -12000,9 +12523,9 @@ msgstr "" #: src/android/interoperability/java.md:75 msgid "" "```shell\n" -"$ m helloworld_jni\n" -"$ adb sync # requires adb root && adb remount\n" -"$ adb shell /system/bin/helloworld_jni\n" +"m helloworld_jni\n" +"adb sync # requires adb root && adb remount\n" +"adb shell /system/bin/helloworld_jni\n" "```" msgstr "" @@ -13246,6 +13769,154 @@ msgid "" "hardware, but is designed purely for virtual machines." msgstr "" +#: src/bare-metal/aps/entry-point.md:3 +msgid "" +"Before we can start running Rust code, we need to do some initialisation." +msgstr "" + +#: src/bare-metal/aps/entry-point.md:5 +msgid "" +"```armasm\n" +".section .init.entry, \"ax\"\n" +".global entry\n" +"entry:\n" +" /*\n" +" * Load and apply the memory management configuration, ready to enable " +"MMU and\n" +" * caches.\n" +" */\n" +" adrp x30, idmap\n" +" msr ttbr0_el1, x30\n" +"\n" +" mov_i x30, .Lmairval\n" +" msr mair_el1, x30\n" +"\n" +" mov_i x30, .Ltcrval\n" +" /* Copy the supported PA range into TCR_EL1.IPS. */\n" +" mrs x29, id_aa64mmfr0_el1\n" +" bfi x30, x29, #32, #4\n" +"\n" +" msr tcr_el1, x30\n" +"\n" +" mov_i x30, .Lsctlrval\n" +"\n" +" /*\n" +" * Ensure everything before this point has completed, then invalidate " +"any\n" +" * potentially stale local TLB entries before they start being used.\n" +" */\n" +" isb\n" +" tlbi vmalle1\n" +" ic iallu\n" +" dsb nsh\n" +" isb\n" +"\n" +" /*\n" +" * Configure sctlr_el1 to enable MMU and cache and don't proceed until " +"this\n" +" * has completed.\n" +" */\n" +" msr sctlr_el1, x30\n" +" isb\n" +"\n" +" /* Disable trapping floating point access in EL1. */\n" +" mrs x30, cpacr_el1\n" +" orr x30, x30, #(0x3 << 20)\n" +" msr cpacr_el1, x30\n" +" isb\n" +"\n" +" /* Zero out the bss section. */\n" +" adr_l x29, bss_begin\n" +" adr_l x30, bss_end\n" +"0: cmp x29, x30\n" +" b.hs 1f\n" +" stp xzr, xzr, [x29], #16\n" +" b 0b\n" +"\n" +"1: /* Prepare the stack. */\n" +" adr_l x30, boot_stack_end\n" +" mov sp, x30\n" +"\n" +" /* Set up exception vector. */\n" +" adr x30, vector_table_el1\n" +" msr vbar_el1, x30\n" +"\n" +" /* Call into Rust code. */\n" +" bl main\n" +"\n" +" /* Loop forever waiting for interrupts. */\n" +"2: wfi\n" +" b 2b\n" +"```" +msgstr "" + +#: src/bare-metal/aps/entry-point.md:77 +msgid "" +"This is the same as it would be for C: initialising the processor state, " +"zeroing the BSS, and setting up the stack pointer." +msgstr "" + +#: src/bare-metal/aps/entry-point.md:79 +msgid "" +"The BSS (block starting symbol, for historical reasons) is the part of the " +"object file which containing statically allocated variables which are " +"initialised to zero. They are omitted from the image, to avoid wasting space " +"on zeroes. The compiler assumes that the loader will take care of zeroing " +"them." +msgstr "" + +#: src/bare-metal/aps/entry-point.md:83 +msgid "" +"The BSS may already be zeroed, depending on how memory is initialised and " +"the image is loaded, but we zero it to be sure." +msgstr "" + +#: src/bare-metal/aps/entry-point.md:85 +msgid "" +"We need to enable the MMU and cache before reading or writing any memory. If " +"we don't:" +msgstr "" + +#: src/bare-metal/aps/entry-point.md:86 +msgid "" +"Unaligned accesses will fault. We build the Rust code for the `aarch64-" +"unknown-none` target which sets `+strict-align` to prevent the compiler " +"generating unaligned accesses, so it should be fine in this case, but this " +"is not necessarily the case in general." +msgstr "" + +#: src/bare-metal/aps/entry-point.md:89 +msgid "" +"If it were running in a VM, this can lead to cache coherency issues. The " +"problem is that the VM is accessing memory directly with the cache disabled, " +"while the host has cachable aliases to the same memory. Even if the host " +"doesn't explicitly access the memory, speculative accesses can lead to cache " +"fills, and then changes from one or the other will get lost when the cache " +"is cleaned or the VM enables the cache. (Cache is keyed by physical address, " +"not VA or IPA.)" +msgstr "" + +#: src/bare-metal/aps/entry-point.md:94 +msgid "" +"For simplicity, we just use a hardcoded pagetable (see `idmap.S`) which " +"identity maps the first 1 GiB of address space for devices, the next 1 GiB " +"for DRAM, and another 1 GiB higher up for more devices. This matches the " +"memory layout that QEMU uses." +msgstr "" + +#: src/bare-metal/aps/entry-point.md:97 +msgid "" +"We also set up the exception vector (`vbar_el1`), which we'll see more about " +"later." +msgstr "" + +#: src/bare-metal/aps/entry-point.md:98 +msgid "" +"All examples this afternoon assume we will be running at exception level 1 " +"(EL1). If you need to run at a different exception level you'll need to " +"modify `entry.S` accordingly." +msgstr "" + #: src/bare-metal/aps/inline-assembly.md:1 msgid "Inline assembly" msgstr "" @@ -13907,9 +14578,9 @@ msgid "" " writeln!(uart, \"main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})\").unwrap();\n" "\n" " loop {\n" -" if let Some(b) = uart.read_byte() {\n" -" uart.write_byte(b);\n" -" match b {\n" +" if let Some(byte) = uart.read_byte() {\n" +" uart.write_byte(byte);\n" +" match byte {\n" " b'\\r' => {\n" " uart.write_byte(b'\\n');\n" " }\n" @@ -14053,6 +14724,98 @@ msgid "" "examples`." msgstr "" +#: src/bare-metal/aps/exceptions.md:3 +msgid "" +"AArch64 defines an exception vector table with 16 entries, for 4 types of " +"exceptions (synchronous, IRQ, FIQ, SError) from 4 states (current EL with " +"SP0, current EL with SPx, lower EL using AArch64, lower EL using AArch32). " +"We implement this in assembly to save volatile registers to the stack before " +"calling into Rust code:" +msgstr "" + +#: src/bare-metal/aps/exceptions.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use log::error;\n" +"use smccc::psci::system_off;\n" +"use smccc::Hvc;\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_exception_current(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_exception_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_current(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_current(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_current\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn sync_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"sync_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn irq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"irq_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn fiq_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"fiq_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"\n" +"#[no_mangle]\n" +"extern \"C\" fn serr_lower(_elr: u64, _spsr: u64) {\n" +" error!(\"serr_lower\");\n" +" system_off::().unwrap();\n" +"}\n" +"```" +msgstr "" + +#: src/bare-metal/aps/exceptions.md:64 +msgid "EL is exception level; all our examples this afternoon run in EL1." +msgstr "" + +#: src/bare-metal/aps/exceptions.md:65 +msgid "" +"For simplicity we aren't distinguishing between SP0 and SPx for the current " +"EL exceptions, or between AArch32 and AArch64 for the lower EL exceptions." +msgstr "" + +#: src/bare-metal/aps/exceptions.md:67 +msgid "" +"For this example we just log the exception and power down, as we don't " +"expect any of them to actually happen." +msgstr "" + +#: src/bare-metal/aps/exceptions.md:69 +msgid "" +"We can think of exception handlers and our main execution context more or " +"less like different threads. [`Send` and `Sync`](../../concurrency/send-sync." +"md) will control what we can share between them, just like with threads. For " +"example, if we want to share some value between exception handlers and the " +"rest of the program, and it's `Send` but not `Sync`, then we'll need to wrap " +"it in something like a `Mutex` and put it in a static." +msgstr "" + #: src/bare-metal/aps/other-projects.md:3 msgid "[oreboot](https://github.com/oreboot/oreboot)" msgstr "" @@ -14081,18 +14844,45 @@ msgid "" "exception handling, page tables" msgstr "" -#: src/bare-metal/aps/other-projects.md:9 -msgid "Not all very well written, so beware." +#: src/bare-metal/aps/other-projects.md:10 +msgid "" +"Some dodginess around cache maintenance and initialisation in Rust, not " +"necessarily a good example to copy for production code." msgstr "" -#: src/bare-metal/aps/other-projects.md:10 +#: src/bare-metal/aps/other-projects.md:12 msgid "[`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)" msgstr "" -#: src/bare-metal/aps/other-projects.md:11 +#: src/bare-metal/aps/other-projects.md:13 msgid "Static analysis to determine maximum stack usage." msgstr "" +#: src/bare-metal/aps/other-projects.md:17 +msgid "" +"The RaspberryPi OS tutorial runs Rust code before the MMU and caches are " +"enabled. This will read and write memory (e.g. the stack). However:" +msgstr "" + +#: src/bare-metal/aps/other-projects.md:19 +msgid "" +"Without the MMU and cache, unaligned accesses will fault. It builds with " +"`aarch64-unknown-none` which sets `+strict-align` to prevent the compiler " +"generating unaligned accesses so it should be alright, but this is not " +"necessarily the case in general." +msgstr "" + +#: src/bare-metal/aps/other-projects.md:22 +msgid "" +"If it were running in a VM, this can lead to cache coherency issues. The " +"problem is that the VM is accessing memory directly with the cache disabled, " +"while the host has cachable aliases to the same memory. Even if the host " +"doesn't explicitly access the memory, speculative accesses can lead to cache " +"fills, and then changes from one or the other will get lost. Again this is " +"alright in this particular case (running directly on the hardware with no " +"hypervisor), but isn't a good pattern in general." +msgstr "" + #: src/bare-metal/useful-crates.md:3 msgid "" "We'll go over a few crates which solve some common problems in bare-metal " @@ -15658,17 +16448,20 @@ msgid "" "```rust,editable,compile_fail\n" "use std::thread;\n" "\n" -"fn main() {\n" +"fn foo() {\n" " let s = String::from(\"Hello\");\n" -"\n" " thread::spawn(|| {\n" " println!(\"Length: {}\", s.len());\n" " });\n" "}\n" +"\n" +"fn main() {\n" +" foo();\n" +"}\n" "```" msgstr "" -#: src/concurrency/scoped-threads.md:17 +#: src/concurrency/scoped-threads.md:20 msgid "" "However, you can use a [scoped thread](https://doc.rust-lang.org/std/thread/" "fn.scope.html) for this:" @@ -15676,7 +16469,7 @@ msgstr "" "しかし、そのために[スコープ付きスレッド](https://doc.rust-lang.org/std/" "thread/fn.scope.html)を使うことができます:" -#: src/concurrency/scoped-threads.md:19 +#: src/concurrency/scoped-threads.md:22 msgid "" "```rust,editable\n" "use std::thread;\n" @@ -15693,7 +16486,7 @@ msgid "" "```" msgstr "" -#: src/concurrency/scoped-threads.md:37 +#: src/concurrency/scoped-threads.md:40 msgid "" "The reason for that is that when the `thread::scope` function completes, all " "the threads are guaranteed to be joined, so they can return borrowed data." @@ -15701,7 +16494,7 @@ msgstr "" "この理由は、関数`thread::scope`が完了するとき、全てのスレッドはjoinされること" "が保証されているので、スレッドが借用したデータを返すことができるためです。" -#: src/concurrency/scoped-threads.md:38 +#: src/concurrency/scoped-threads.md:41 msgid "" "Normal Rust borrowing rules apply: you can either borrow mutably by one " "thread, or immutably by any number of threads." @@ -15791,7 +16584,8 @@ msgid "" msgstr "" #: src/concurrency/channels/bounded.md:3 -msgid "Bounded and synchronous channels make `send` block the current thread:" +msgid "" +"With bounded (synchronous) channels, `send` can block the current thread:" msgstr "" #: src/concurrency/channels/bounded.md:5 @@ -15821,6 +16615,25 @@ msgid "" "```" msgstr "" +#: src/concurrency/channels/bounded.md:31 +msgid "" +"Calling `send` will block the current thread until there is space in the " +"channel for the new message. The thread can be blocked indefinitely if there " +"is nobody who reads from the channel." +msgstr "" + +#: src/concurrency/channels/bounded.md:32 +msgid "" +"A call to `send` will abort with an error (that is why it returns `Result`) " +"if the channel is closed. A channel is closed when the receiver is dropped." +msgstr "" + +#: src/concurrency/channels/bounded.md:33 +msgid "" +"A bounded channel with a size of zero is called a \"rendezvous channel\". " +"Every send will block the current thread until another thread calls `read`." +msgstr "" + #: src/concurrency/send-sync.md:1 msgid "`Send` and `Sync`" msgstr "" @@ -16078,7 +16891,7 @@ msgstr "" #: src/concurrency/shared_state/arc.md:31 msgid "" "`Arc` implements `Clone` whether or not `T` does. It implements `Send` " -"and `Sync` iff `T` implements them both." +"and `Sync` if and only if `T` implements them both." msgstr "" #: src/concurrency/shared_state/arc.md:33 @@ -16153,7 +16966,9 @@ msgid "" msgstr "" #: src/concurrency/shared_state/mutex.md:35 -msgid "`Mutex` implements both `Send` and `Sync` iff `T` implements `Send`." +msgid "" +"`Mutex` implements both `Send` and `Sync` iff (if and only if) `T` " +"implements `Send`." msgstr "" #: src/concurrency/shared_state/mutex.md:36 @@ -16330,7 +17145,7 @@ msgid "" "\n" " // Create philosophers\n" "\n" -" // Make them think and eat\n" +" // Make each of them think and eat 100 times\n" "\n" " // Output their thoughts\n" "}\n" @@ -16368,9 +17183,9 @@ msgstr "" #: src/exercises/concurrency/link-checker.md:11 msgid "" "```shell\n" -"$ cargo new link-checker\n" -"$ cd link-checker\n" -"$ cargo add --features blocking,rustls-tls reqwest\n" +"cargo new link-checker\n" +"cd link-checker\n" +"cargo add --features blocking,rustls-tls reqwest\n" "```" msgstr "" @@ -16389,7 +17204,7 @@ msgstr "" #: src/exercises/concurrency/link-checker.md:22 msgid "" "```shell\n" -"$ cargo add scraper\n" +"cargo add scraper\n" "```" msgstr "" @@ -16402,7 +17217,7 @@ msgstr "" #: src/exercises/concurrency/link-checker.md:29 msgid "" "```shell\n" -"$ cargo add thiserror\n" +"cargo add thiserror\n" "```" msgstr "" @@ -16441,8 +17256,7 @@ msgstr "" #: src/exercises/concurrency/link-checker.md:57 msgid "" "```rust,compile_fail\n" -"use reqwest::blocking::{get, Response};\n" -"use reqwest::Url;\n" +"use reqwest::{blocking::Client, Url};\n" "use scraper::{Html, Selector};\n" "use thiserror::Error;\n" "\n" @@ -16450,34 +17264,57 @@ msgid "" "enum Error {\n" " #[error(\"request error: {0}\")]\n" " ReqwestError(#[from] reqwest::Error),\n" +" #[error(\"bad http response: {0}\")]\n" +" BadResponse(String),\n" "}\n" "\n" -"fn extract_links(response: Response) -> Result, Error> {\n" -" let base_url = response.url().to_owned();\n" -" let document = response.text()?;\n" -" let html = Html::parse_document(&document);\n" -" let selector = Selector::parse(\"a\").unwrap();\n" +"#[derive(Debug)]\n" +"struct CrawlCommand {\n" +" url: Url,\n" +" extract_links: bool,\n" +"}\n" "\n" -" let mut valid_urls = Vec::new();\n" -" for element in html.select(&selector) {\n" -" if let Some(href) = element.value().attr(\"href\") {\n" -" match base_url.join(href) {\n" -" Ok(url) => valid_urls.push(url),\n" -" Err(err) => {\n" -" println!(\"On {base_url}: could not parse {href:?}: " -"{err} (ignored)\",);\n" -" }\n" +"fn visit_page(client: &Client, command: &CrawlCommand) -> Result, " +"Error> {\n" +" println!(\"Checking {:#}\", command.url);\n" +" let response = client.get(command.url.clone()).send()?;\n" +" if !response.status().is_success() {\n" +" return Err(Error::BadResponse(response.status().to_string()));\n" +" }\n" +"\n" +" let mut link_urls = Vec::new();\n" +" if !command.extract_links {\n" +" return Ok(link_urls);\n" +" }\n" +"\n" +" let base_url = response.url().to_owned();\n" +" let body_text = response.text()?;\n" +" let document = Html::parse_document(&body_text);\n" +"\n" +" let selector = Selector::parse(\"a\").unwrap();\n" +" let href_values = document\n" +" .select(&selector)\n" +" .filter_map(|element| element.value().attr(\"href\"));\n" +" for href in href_values {\n" +" match base_url.join(href) {\n" +" Ok(link_url) => {\n" +" link_urls.push(link_url);\n" +" }\n" +" Err(err) => {\n" +" println!(\"On {base_url:#}: ignored unparsable {href:?}: " +"{err}\");\n" " }\n" " }\n" " }\n" -"\n" -" Ok(valid_urls)\n" +" Ok(link_urls)\n" "}\n" "\n" "fn main() {\n" +" let client = Client::new();\n" " let start_url = Url::parse(\"https://www.google.org\").unwrap();\n" -" let response = get(start_url).unwrap();\n" -" match extract_links(response) {\n" +" let crawl_command = CrawlCommand{ url: start_url, extract_links: " +"true };\n" +" match visit_page(&client, &crawl_command) {\n" " Ok(links) => println!(\"Links: {links:#?}\"),\n" " Err(err) => println!(\"Could not extract links: {err:#}\"),\n" " }\n" @@ -16485,24 +17322,24 @@ msgid "" "```" msgstr "" -#: src/exercises/concurrency/link-checker.md:100 +#: src/exercises/concurrency/link-checker.md:120 msgid "Run the code in `src/main.rs` with" msgstr "" -#: src/exercises/concurrency/link-checker.md:102 +#: src/exercises/concurrency/link-checker.md:122 msgid "" "```shell\n" -"$ cargo run\n" +"cargo run\n" "```" msgstr "" -#: src/exercises/concurrency/link-checker.md:108 +#: src/exercises/concurrency/link-checker.md:128 msgid "" "Use threads to check the links in parallel: send the URLs to be checked to a " "channel and let a few threads check the URLs in parallel." msgstr "" -#: src/exercises/concurrency/link-checker.md:110 +#: src/exercises/concurrency/link-checker.md:130 msgid "" "Extend this to recursively extract links from all pages on the `www.google." "org` domain. Put an upper limit of 100 pages or so so that you don't end up " @@ -16759,8 +17596,9 @@ msgstr "" "りませんが、いくつかのランタイムの選択肢があります: " #: src/async/runtimes.md:7 +#, fuzzy msgid "" -"[Tokio](https://tokio.rs/) - performant, with a well-developed ecosystem of " +"[Tokio](https://tokio.rs/): performant, with a well-developed ecosystem of " "functionality like [Hyper](https://hyper.rs/) for HTTP or [Tonic](https://" "github.com/hyperium/tonic) for gRPC." msgstr "" @@ -16769,15 +17607,17 @@ msgstr "" "したエコシステムも持っている" #: src/async/runtimes.md:10 +#, fuzzy msgid "" -"[async-std](https://async.rs/) - aims to be a \"std for async\", and " -"includes a basic runtime in `async::task`." +"[async-std](https://async.rs/): aims to be a \"std for async\", and includes " +"a basic runtime in `async::task`." msgstr "" "[async-std](https://async.rs/) - 「async」のための「std」であることを目指した" "もの。また、`async::task`に基本的なランタイムを含む。" #: src/async/runtimes.md:12 -msgid "[smol](https://docs.rs/smol/latest/smol/) - simple and lightweight" +#, fuzzy +msgid "[smol](https://docs.rs/smol/latest/smol/): simple and lightweight" msgstr "[smol](https://docs.rs/smol/latest/smol/) - シンプルで軽量" #: src/async/runtimes.md:14 @@ -16890,14 +17730,10 @@ msgid "Try awaiting the task returned from `tokio::spawn`." msgstr "`tokio::spawn`から返されたタスクを待機してみてください。" #: src/async/tasks.md:3 -msgid "" -"Runtimes have the concept of a \"task\", similar to a thread but much less " -"resource-intensive." +msgid "Rust has a task system, which is a form of lightweight threading." msgstr "" -"ランタイムには「タスク」という概念があり、スレッドに似ているものの、スレッド" -"よりリソースの消費ははるかに小さいです。" -#: src/async/tasks.md:6 +#: src/async/tasks.md:5 msgid "" "A task has a single top-level future which the executor polls to make " "progress. That future may have one or more nested futures that its `poll` " @@ -16912,7 +17748,7 @@ msgstr "" "行処理は、例えば競合タイマーや入出力操作など、複数の子のfutureをポーリングす" "ることにより可能になります。" -#: src/async/tasks.md:11 +#: src/async/tasks.md:10 msgid "" "```rust,compile_fail\n" "use tokio::io::{self, AsyncReadExt, AsyncWriteExt};\n" @@ -16956,13 +17792,13 @@ msgid "" "```" msgstr "" -#: src/async/tasks.md:53 src/async/control-flow/join.md:36 +#: src/async/tasks.md:52 src/async/control-flow/join.md:36 msgid "" "Copy this example into your prepared `src/main.rs` and run it from there." msgstr "" "この例を準備した`src/main.rs`にコピーして、そこから実行してみましょう。" -#: src/async/tasks.md:55 +#: src/async/tasks.md:54 msgid "" "Ask students to visualize what the state of the example server would be with " "a few connected clients. What tasks exist? What are their Futures?" @@ -16971,7 +17807,7 @@ msgstr "" "あるのかを、可視化するように受講者に指示してください。どんなタスクが存在して" "いますか?それらのfutureは何ですか?" -#: src/async/tasks.md:58 +#: src/async/tasks.md:57 msgid "" "This is the first time we've seen an `async` block. This is similar to a " "closure, but does not take any arguments. Its return value is a Future, " @@ -16981,7 +17817,7 @@ msgstr "" "すが、何も引数は取りません。この返り値はFutureであり、`async fn`と似ていま" "す。" -#: src/async/tasks.md:62 +#: src/async/tasks.md:61 msgid "" "Refactor the async block into a function, and improve the error handling " "using `?`." @@ -16990,9 +17826,9 @@ msgstr "" "善してみましょう。" #: src/async/channels.md:3 +#, fuzzy msgid "" -"Several crates have support for `async`/`await`. For instance `tokio` " -"channels:" +"Several crates have support for asynchronous channels. For instance `tokio`:" msgstr "" "いくつかのクレートは`async`/`await`をサポートしています。例えば、`tokio`チャ" "ネルは:" @@ -17022,7 +17858,7 @@ msgid "" " println!(\"Sent {} pings so far.\", i + 1);\n" " }\n" "\n" -" std::mem::drop(sender);\n" +" drop(sender);\n" " ping_handler_task.await.expect(\"Something went wrong in ping handler " "task.\");\n" "}\n" @@ -17156,12 +17992,13 @@ msgstr "" #: src/async/control-flow/select.md:8 msgid "" -"This is usually a macro, similar to match, with each arm of the form " -"`pattern = future => statement`. When the future is ready, the statement is " -"executed with the variable bound to the future's result." +"Similar to a match statement, the body of `select!` has a number of arms, " +"each of the form `pattern = future => statement`. When the `future` is " +"ready, the `statement` is executed with the variables in `pattern` bound to " +"the `future`'s result." msgstr "" -#: src/async/control-flow/select.md:12 +#: src/async/control-flow/select.md:13 msgid "" "```rust,editable,compile_fail\n" "use tokio::sync::mpsc::{self, Receiver};\n" @@ -17211,7 +18048,7 @@ msgid "" "```" msgstr "" -#: src/async/control-flow/select.md:61 +#: src/async/control-flow/select.md:62 msgid "" "In this example, we have a race between a cat and a dog. " "`first_animal_to_finish_race` listens to both channels and will pick " @@ -17219,24 +18056,28 @@ msgid "" "that take 500ms seconds." msgstr "" -#: src/async/control-flow/select.md:66 +#: src/async/control-flow/select.md:67 msgid "" "You can use `oneshot` channels in this example as the channels are supposed " "to receive only one `send`." msgstr "" -#: src/async/control-flow/select.md:69 +#: src/async/control-flow/select.md:70 msgid "" "Try adding a deadline to the race, demonstrating selecting different sorts " "of futures." msgstr "" -#: src/async/control-flow/select.md:72 +#: src/async/control-flow/select.md:73 msgid "" -"Note that `select!` moves the values it is given. It is easiest to use when " -"every execution of `select!` creates new futures. An alternative is to pass " -"`&mut future` instead of the future itself, but this can lead to issues, " -"further discussed in the pinning slide." +"Note that `select!` drops unmatched branches, which cancels their futures. " +"It is easiest to use when every execution of `select!` creates new futures." +msgstr "" + +#: src/async/control-flow/select.md:76 +msgid "" +"An alternative is to pass `&mut future` instead of the future itself, but " +"this can lead to issues, further discussed in the pinning slide." msgstr "" #: src/async/pitfalls.md:1 @@ -17260,7 +18101,11 @@ msgid "[Pin](pitfalls/pin.md)" msgstr "" #: src/async/pitfalls.md:7 -msgid "[Async Traits](pitfall/async-traits.md)" +msgid "[Async Traits](pitfalls/async-traits.md)" +msgstr "" + +#: src/async/pitfalls.md:8 +msgid "[Cancellation](pitfalls/cancellation.md)" msgstr "" #: src/async/pitfalls/blocking-executor.md:1 @@ -17567,6 +18412,155 @@ msgid "" "time and adding it to the Vec." msgstr "" +#: src/async/pitfalls/cancellation.md:3 +msgid "" +"Dropping a future implies it can never be polled again. This is called " +"_cancellation_ and it can occur at any `await` point. Care is needed to " +"ensure the system works correctly even when futures are cancelled. For " +"example, it shouldn't deadlock or lose data." +msgstr "" + +#: src/async/pitfalls/cancellation.md:8 +msgid "" +"```rust,editable,compile_fail\n" +"use std::io::{self, ErrorKind};\n" +"use std::time::Duration;\n" +"use tokio::io::{AsyncReadExt, AsyncWriteExt, DuplexStream};\n" +"\n" +"struct LinesReader {\n" +" stream: DuplexStream,\n" +"}\n" +"\n" +"impl LinesReader {\n" +" fn new(stream: DuplexStream) -> Self {\n" +" Self { stream }\n" +" }\n" +"\n" +" async fn next(&mut self) -> io::Result> {\n" +" let mut bytes = Vec::new();\n" +" let mut buf = [0];\n" +" while self.stream.read(&mut buf[..]).await? != 0 {\n" +" bytes.push(buf[0]);\n" +" if buf[0] == b'\\n' {\n" +" break;\n" +" }\n" +" }\n" +" if bytes.is_empty() {\n" +" return Ok(None)\n" +" }\n" +" let s = String::from_utf8(bytes)\n" +" .map_err(|_| io::Error::new(ErrorKind::InvalidData, \"not " +"UTF-8\"))?;\n" +" Ok(Some(s))\n" +" }\n" +"}\n" +"\n" +"async fn slow_copy(source: String, mut dest: DuplexStream) -> std::io::" +"Result<()> {\n" +" for b in source.bytes() {\n" +" dest.write_u8(b).await?;\n" +" tokio::time::sleep(Duration::from_millis(10)).await\n" +" }\n" +" Ok(())\n" +"}\n" +"\n" +"#[tokio::main]\n" +"async fn main() -> std::io::Result<()> {\n" +" let (client, server) = tokio::io::duplex(5);\n" +" let handle = tokio::spawn(slow_copy(\"hi\\nthere\\n\".to_owned(), " +"client));\n" +"\n" +" let mut lines = LinesReader::new(server);\n" +" let mut interval = tokio::time::interval(Duration::from_millis(60));\n" +" loop {\n" +" tokio::select! {\n" +" _ = interval.tick() => println!(\"tick!\"),\n" +" line = lines.next() => if let Some(l) = line? {\n" +" print!(\"{}\", l)\n" +" } else {\n" +" break\n" +" },\n" +" }\n" +" }\n" +" handle.await.unwrap()?;\n" +" Ok(())\n" +"}\n" +"```" +msgstr "" + +#: src/async/pitfalls/cancellation.md:72 +msgid "" +"The compiler doesn't help with cancellation-safety. You need to read API " +"documentation and consider what state your `async fn` holds." +msgstr "" + +#: src/async/pitfalls/cancellation.md:75 +msgid "" +"Unlike `panic` and `?`, cancellation is part of normal control flow (vs " +"error-handling)." +msgstr "" + +#: src/async/pitfalls/cancellation.md:78 +msgid "The example loses parts of the string." +msgstr "" + +#: src/async/pitfalls/cancellation.md:80 +msgid "" +"Whenever the `tick()` branch finishes first, `next()` and its `buf` are " +"dropped." +msgstr "" + +#: src/async/pitfalls/cancellation.md:82 +msgid "" +"`LinesReader` can be made cancellation-safe by makeing `buf` part of the " +"struct:" +msgstr "" + +#: src/async/pitfalls/cancellation.md:83 +msgid "" +"```rust,compile_fail\n" +"struct LinesReader {\n" +" stream: DuplexStream,\n" +" bytes: Vec,\n" +" buf: [u8; 1],\n" +"}\n" +"\n" +"impl LinesReader {\n" +" fn new(stream: DuplexStream) -> Self {\n" +" Self { stream, bytes: Vec::new(), buf: [0] }\n" +" }\n" +" async fn next(&mut self) -> io::Result> {\n" +" // prefix buf and bytes with self.\n" +" // ...\n" +" let raw = std::mem::take(&mut self.bytes);\n" +" let s = String::from_utf8(raw)\n" +" // ...\n" +" }\n" +"}\n" +"```" +msgstr "" + +#: src/async/pitfalls/cancellation.md:104 +msgid "" +"[`Interval::tick`](https://docs.rs/tokio/latest/tokio/time/struct.Interval." +"html#method.tick) is cancellation-safe because it keeps track of whether a " +"tick has been 'delivered'." +msgstr "" + +#: src/async/pitfalls/cancellation.md:107 +msgid "" +"[`AsyncReadExt::read`](https://docs.rs/tokio/latest/tokio/io/trait." +"AsyncReadExt.html#method.read) is cancellation-safe because it either " +"returns or doesn't read data." +msgstr "" + +#: src/async/pitfalls/cancellation.md:110 +msgid "" +"[`AsyncBufReadExt::read_line`](https://docs.rs/tokio/latest/tokio/io/trait." +"AsyncBufReadExt.html#method.read_line) is similar to the example and _isn't_ " +"cancellation-safe. See its documentation for details and alternatives." +msgstr "" + #: src/exercises/concurrency/afternoon.md:3 msgid "" "To practice your Async Rust skills, we have again two exercises for you:" @@ -17749,7 +18743,7 @@ msgstr "" #: src/exercises/concurrency/chat-app.md:41 msgid "" -"[BufReader::read_line()](https://docs.rs/tokio/latest/tokio/io/struct.Lines." +"[Lines::next_line()](https://docs.rs/tokio/latest/tokio/io/struct.Lines." "html#method.next_line): for asynchronously reading user messages from the " "standard input." msgstr "" @@ -17783,7 +18777,7 @@ msgid "" msgstr "" #: src/exercises/concurrency/chat-app.md:59 -#: src/exercises/concurrency/solutions-afternoon.md:117 +#: src/exercises/concurrency/solutions-afternoon.md:123 msgid "`src/bin/server.rs`:" msgstr "" @@ -17830,7 +18824,7 @@ msgid "" msgstr "" #: src/exercises/concurrency/chat-app.md:102 -#: src/exercises/concurrency/solutions-afternoon.md:202 +#: src/exercises/concurrency/solutions-afternoon.md:208 msgid "`src/bin/client.rs`:" msgstr "" @@ -17850,7 +18844,7 @@ msgid "" " .await?;\n" "\n" " let stdin = tokio::io::stdin();\n" -" let mut stdin = BufReader::new(stdin);\n" +" let mut stdin = BufReader::new(stdin).lines();\n" "\n" "\n" " // TODO: For a hint, see the description of the task below.\n" @@ -17870,7 +18864,7 @@ msgstr "" #: src/exercises/concurrency/chat-app.md:130 msgid "" "```shell\n" -"$ cargo run --bin server\n" +"cargo run --bin server\n" "```" msgstr "" @@ -17881,7 +18875,7 @@ msgstr "" #: src/exercises/concurrency/chat-app.md:136 msgid "" "```shell\n" -"$ cargo run --bin client\n" +"cargo run --bin client\n" "```" msgstr "" @@ -18072,14 +19066,15 @@ msgstr "" #: src/credits.md:7 msgid "" "The material of Comprehensive Rust is licensed under the terms of the Apache " -"2.0 license, please see [`LICENSE`](../LICENSE) for details." -msgstr "" - -#: src/credits.md:10 -msgid "Rust by Example" +"2.0 license, please see [`LICENSE`](https://github.com/google/comprehensive-" +"rust/blob/main/LICENSE) for details." msgstr "" #: src/credits.md:12 +msgid "Rust by Example" +msgstr "" + +#: src/credits.md:14 msgid "" "Some examples and exercises have been copied and adapted from [Rust by " "Example](https://doc.rust-lang.org/rust-by-example/). Please see the " @@ -18087,22 +19082,22 @@ msgid "" "terms." msgstr "" -#: src/credits.md:17 +#: src/credits.md:19 msgid "Rust on Exercism" msgstr "" -#: src/credits.md:19 +#: src/credits.md:21 msgid "" "Some exercises have been copied and adapted from [Rust on Exercism](https://" "exercism.org/tracks/rust). Please see the `third_party/rust-on-exercism/` " "directory for details, including the license terms." msgstr "" -#: src/credits.md:24 +#: src/credits.md:26 msgid "CXX" msgstr "" -#: src/credits.md:26 +#: src/credits.md:28 msgid "" "The [Interoperability with C++](android/interoperability/cpp.md) section " "uses an image from [CXX](https://cxx.rs/). Please see the `third_party/cxx/` " @@ -18277,7 +19272,7 @@ msgid "Day 1 Afternoon Exercises" msgstr "" #: src/exercises/day-1/solutions-afternoon.md:5 -msgid "([back to exercise](book-library.md))" +msgid "([back to exercise](luhn.md))" msgstr "" #: src/exercises/day-1/solutions-afternoon.md:7 @@ -18297,6 +19292,121 @@ msgid "" "// See the License for the specific language governing permissions and\n" "// limitations under the License.\n" "\n" +"// ANCHOR: luhn\n" +"pub fn luhn(cc_number: &str) -> bool {\n" +" // ANCHOR_END: luhn\n" +" let mut digits_seen = 0;\n" +" let mut sum = 0;\n" +" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ')." +"enumerate() {\n" +" match ch.to_digit(10) {\n" +" Some(d) => {\n" +" sum += if i % 2 == 1 {\n" +" let dd = d * 2;\n" +" dd / 10 + dd % 10\n" +" } else {\n" +" d\n" +" };\n" +" digits_seen += 1;\n" +" }\n" +" None => return false,\n" +" }\n" +" }\n" +"\n" +" if digits_seen < 2 {\n" +" return false;\n" +" }\n" +"\n" +" sum % 10 == 0\n" +"}\n" +"\n" +"fn main() {\n" +" let cc_number = \"1234 5678 1234 5670\";\n" +" println!(\n" +" \"Is {cc_number} a valid credit card number? {}\",\n" +" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" +" );\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[test]\n" +"fn test_non_digit_cc_number() {\n" +" assert!(!luhn(\"foo\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_empty_cc_number() {\n" +" assert!(!luhn(\"\"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +" assert!(!luhn(\" \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_single_digit_cc_number() {\n" +" assert!(!luhn(\"0\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_two_digit_cc_number() {\n" +" assert!(luhn(\" 0 0 \"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_valid_cc_number() {\n" +" assert!(luhn(\"4263 9826 4026 9299\"));\n" +" assert!(luhn(\"4539 3195 0343 6467\"));\n" +" assert!(luhn(\"7992 7398 713\"));\n" +"}\n" +"\n" +"#[test]\n" +"fn test_invalid_cc_number() {\n" +" assert!(!luhn(\"4223 9826 4026 9299\"));\n" +" assert!(!luhn(\"4539 3195 0343 6476\"));\n" +" assert!(!luhn(\"8273 1232 7352 0569\"));\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"```" +msgstr "" + +#: src/exercises/day-1/solutions-afternoon.md:97 +#, fuzzy +msgid "Pattern matching" +msgstr "パターンマッチング" + +#: src/exercises/day-1/solutions-afternoon.md:99 +msgid "TBD." +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:1 +msgid "Day 2 Morning Exercises" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:3 +msgid "Designing a Library" +msgstr "ライブラリをデザイン" + +#: src/exercises/day-2/solutions-morning.md:5 +msgid "([back to exercise](book-library.md))" +msgstr "" + +#: src/exercises/day-2/solutions-morning.md:7 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" "// ANCHOR: setup\n" "struct Library {\n" " books: Vec,\n" @@ -18400,13 +19510,15 @@ msgid "" "fn main() {\n" " let library = Library::new();\n" "\n" -" //println!(\"The library is empty: {}\", library.is_empty());\n" +" //println!(\"The library is empty: library.is_empty() -> {}\", library." +"is_empty());\n" " //\n" " //library.add_book(Book::new(\"Lord of the Rings\", 1954));\n" " //library.add_book(Book::new(\"Alice's Adventures in Wonderland\", " "1865));\n" " //\n" -" //println!(\"The library is no longer empty: {}\", library.is_empty());\n" +" //println!(\"The library is no longer empty: library.is_empty() -> {}\", " +"library.is_empty());\n" " //\n" " //\n" " //library.print_books();\n" @@ -18475,252 +19587,12 @@ msgid "" "```" msgstr "" -#: src/exercises/day-2/solutions-morning.md:1 -msgid "Day 2 Morning Exercises" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:5 -msgid "([back to exercise](points-polygons.md))" -msgstr "" - -#: src/exercises/day-2/solutions-morning.md:7 -msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" -"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" -"// ANCHOR: Point\n" -"pub struct Point {\n" -" // ANCHOR_END: Point\n" -" x: i32,\n" -" y: i32,\n" -"}\n" -"\n" -"// ANCHOR: Point-impl\n" -"impl Point {\n" -" // ANCHOR_END: Point-impl\n" -" pub fn new(x: i32, y: i32) -> Point {\n" -" Point { x, y }\n" -" }\n" -"\n" -" pub fn magnitude(self) -> f64 {\n" -" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" -" }\n" -"\n" -" pub fn dist(self, other: Point) -> f64 {\n" -" (self - other).magnitude()\n" -" }\n" -"}\n" -"\n" -"impl std::ops::Add for Point {\n" -" type Output = Self;\n" -"\n" -" fn add(self, other: Self) -> Self::Output {\n" -" Self {\n" -" x: self.x + other.x,\n" -" y: self.y + other.y,\n" -" }\n" -" }\n" -"}\n" -"\n" -"impl std::ops::Sub for Point {\n" -" type Output = Self;\n" -"\n" -" fn sub(self, other: Self) -> Self::Output {\n" -" Self {\n" -" x: self.x - other.x,\n" -" y: self.y - other.y,\n" -" }\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Polygon\n" -"pub struct Polygon {\n" -" // ANCHOR_END: Polygon\n" -" points: Vec,\n" -"}\n" -"\n" -"// ANCHOR: Polygon-impl\n" -"impl Polygon {\n" -" // ANCHOR_END: Polygon-impl\n" -" pub fn new() -> Polygon {\n" -" Polygon { points: Vec::new() }\n" -" }\n" -"\n" -" pub fn add_point(&mut self, point: Point) {\n" -" self.points.push(point);\n" -" }\n" -"\n" -" pub fn left_most_point(&self) -> Option {\n" -" self.points.iter().min_by_key(|p| p.x).copied()\n" -" }\n" -"\n" -" pub fn iter(&self) -> impl Iterator {\n" -" self.points.iter()\n" -" }\n" -"\n" -" pub fn length(&self) -> f64 {\n" -" if self.points.is_empty() {\n" -" return 0.0;\n" -" }\n" -"\n" -" let mut result = 0.0;\n" -" let mut last_point = self.points[0];\n" -" for point in &self.points[1..] {\n" -" result += last_point.dist(*point);\n" -" last_point = *point;\n" -" }\n" -" result += last_point.dist(self.points[0]);\n" -" result\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Circle\n" -"pub struct Circle {\n" -" // ANCHOR_END: Circle\n" -" center: Point,\n" -" radius: i32,\n" -"}\n" -"\n" -"// ANCHOR: Circle-impl\n" -"impl Circle {\n" -" // ANCHOR_END: Circle-impl\n" -" pub fn new(center: Point, radius: i32) -> Circle {\n" -" Circle { center, radius }\n" -" }\n" -"\n" -" pub fn circumference(&self) -> f64 {\n" -" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" -" }\n" -"\n" -" pub fn dist(&self, other: &Self) -> f64 {\n" -" self.center.dist(other.center)\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: Shape\n" -"pub enum Shape {\n" -" Polygon(Polygon),\n" -" Circle(Circle),\n" -"}\n" -"// ANCHOR_END: Shape\n" -"\n" -"impl From for Shape {\n" -" fn from(poly: Polygon) -> Self {\n" -" Shape::Polygon(poly)\n" -" }\n" -"}\n" -"\n" -"impl From for Shape {\n" -" fn from(circle: Circle) -> Self {\n" -" Shape::Circle(circle)\n" -" }\n" -"}\n" -"\n" -"impl Shape {\n" -" pub fn perimeter(&self) -> f64 {\n" -" match self {\n" -" Shape::Polygon(poly) => poly.length(),\n" -" Shape::Circle(circle) => circle.circumference(),\n" -" }\n" -" }\n" -"}\n" -"\n" -"// ANCHOR: unit-tests\n" -"#[cfg(test)]\n" -"mod tests {\n" -" use super::*;\n" -"\n" -" fn round_two_digits(x: f64) -> f64 {\n" -" (x * 100.0).round() / 100.0\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_magnitude() {\n" -" let p1 = Point::new(12, 13);\n" -" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_dist() {\n" -" let p1 = Point::new(10, 10);\n" -" let p2 = Point::new(14, 13);\n" -" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_point_add() {\n" -" let p1 = Point::new(16, 16);\n" -" let p2 = p1 + Point::new(-4, 3);\n" -" assert_eq!(p2, Point::new(12, 19));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_left_most_point() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -" assert_eq!(poly.left_most_point(), Some(p1));\n" -" }\n" -"\n" -" #[test]\n" -" fn test_polygon_iter() {\n" -" let p1 = Point::new(12, 13);\n" -" let p2 = Point::new(16, 16);\n" -"\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(p1);\n" -" poly.add_point(p2);\n" -"\n" -" let points = poly.iter().cloned().collect::>();\n" -" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" -" }\n" -"\n" -" #[test]\n" -" fn test_shape_perimeters() {\n" -" let mut poly = Polygon::new();\n" -" poly.add_point(Point::new(12, 13));\n" -" poly.add_point(Point::new(17, 11));\n" -" poly.add_point(Point::new(16, 16));\n" -" let shapes = vec![\n" -" Shape::from(poly),\n" -" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" -" ];\n" -" let perimeters = shapes\n" -" .iter()\n" -" .map(Shape::perimeter)\n" -" .map(round_two_digits)\n" -" .collect::>();\n" -" assert_eq!(perimeters, vec![15.48, 31.42]);\n" -" }\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"\n" -"fn main() {}\n" -"```" -msgstr "" - #: src/exercises/day-2/solutions-afternoon.md:1 msgid "Day 2 Afternoon Exercises" msgstr "" #: src/exercises/day-2/solutions-afternoon.md:5 -msgid "([back to exercise](luhn.md))" +msgid "([back to exercise](strings-iterators.md))" msgstr "" #: src/exercises/day-2/solutions-afternoon.md:7 @@ -18740,124 +19612,33 @@ msgid "" "// See the License for the specific language governing permissions and\n" "// limitations under the License.\n" "\n" -"// ANCHOR: luhn\n" -"pub fn luhn(cc_number: &str) -> bool {\n" -" // ANCHOR_END: luhn\n" -" let mut digits_seen = 0;\n" -" let mut sum = 0;\n" -" for (i, ch) in cc_number.chars().rev().filter(|&ch| ch != ' ')." -"enumerate() {\n" -" match ch.to_digit(10) {\n" -" Some(d) => {\n" -" sum += if i % 2 == 1 {\n" -" let dd = d * 2;\n" -" dd / 10 + dd % 10\n" -" } else {\n" -" d\n" -" };\n" -" digits_seen += 1;\n" -" }\n" -" None => return false,\n" -" }\n" -" }\n" -"\n" -" if digits_seen < 2 {\n" -" return false;\n" -" }\n" -"\n" -" sum % 10 == 0\n" -"}\n" -"\n" -"fn main() {\n" -" let cc_number = \"1234 5678 1234 5670\";\n" -" println!(\n" -" \"Is {cc_number} a valid credit card number? {}\",\n" -" if luhn(cc_number) { \"yes\" } else { \"no\" }\n" -" );\n" -"}\n" -"\n" -"// ANCHOR: unit-tests\n" -"#[test]\n" -"fn test_non_digit_cc_number() {\n" -" assert!(!luhn(\"foo\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_empty_cc_number() {\n" -" assert!(!luhn(\"\"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -" assert!(!luhn(\" \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_single_digit_cc_number() {\n" -" assert!(!luhn(\"0\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_two_digit_cc_number() {\n" -" assert!(luhn(\" 0 0 \"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_valid_cc_number() {\n" -" assert!(luhn(\"4263 9826 4026 9299\"));\n" -" assert!(luhn(\"4539 3195 0343 6467\"));\n" -" assert!(luhn(\"7992 7398 713\"));\n" -"}\n" -"\n" -"#[test]\n" -"fn test_invalid_cc_number() {\n" -" assert!(!luhn(\"4223 9826 4026 9299\"));\n" -" assert!(!luhn(\"4539 3195 0343 6476\"));\n" -" assert!(!luhn(\"8273 1232 7352 0569\"));\n" -"}\n" -"// ANCHOR_END: unit-tests\n" -"```" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:99 -msgid "([back to exercise](strings-iterators.md))" -msgstr "" - -#: src/exercises/day-2/solutions-afternoon.md:101 -msgid "" -"```rust\n" -"// Copyright 2022 Google LLC\n" -"//\n" -"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" -"// you may not use this file except in compliance with the License.\n" -"// You may obtain a copy of the License at\n" -"//\n" -"// http://www.apache.org/licenses/LICENSE-2.0\n" -"//\n" -"// Unless required by applicable law or agreed to in writing, software\n" -"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" -"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" -"// See the License for the specific language governing permissions and\n" -"// limitations under the License.\n" -"\n" "// ANCHOR: prefix_matches\n" "pub fn prefix_matches(prefix: &str, request_path: &str) -> bool {\n" " // ANCHOR_END: prefix_matches\n" -" let prefixes = prefix.split('/');\n" -" let request_paths = request_path\n" -" .split('/')\n" -" .map(|p| Some(p))\n" -" .chain(std::iter::once(None));\n" "\n" -" for (prefix, request_path) in prefixes.zip(request_paths) {\n" -" match request_path {\n" -" Some(request_path) => {\n" -" if (prefix != \"*\") && (prefix != request_path) {\n" -" return false;\n" -" }\n" -" }\n" -" None => return false,\n" +" let mut request_segments = request_path.split('/');\n" +"\n" +" for prefix_segment in prefix.split('/') {\n" +" let Some(request_segment) = request_segments.next() else {\n" +" return false;\n" +" };\n" +" if request_segment != prefix_segment && prefix_segment != \"*\" {\n" +" return false;\n" " }\n" " }\n" " true\n" +"\n" +" // Alternatively, Iterator::zip() lets us iterate simultaneously over " +"prefix\n" +" // and request segments. The zip() iterator is finished as soon as one " +"of\n" +" // the source iterators is finished, but we need to iterate over all " +"request\n" +" // segments. A neat trick that makes zip() work is to use map() and " +"chain()\n" +" // to produce an iterator that returns Some(str) for each pattern " +"segments,\n" +" // and then returns None indefinitely.\n" "}\n" "\n" "// ANCHOR: unit-tests\n" @@ -19083,6 +19864,253 @@ msgid "" "```" msgstr "" +#: src/exercises/day-3/solutions-morning.md:177 +msgid "([back to exercise](points-polygons.md))" +msgstr "" + +#: src/exercises/day-3/solutions-morning.md:179 +msgid "" +"```rust\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"#[derive(Debug, Copy, Clone, PartialEq, Eq)]\n" +"// ANCHOR: Point\n" +"pub struct Point {\n" +" // ANCHOR_END: Point\n" +" x: i32,\n" +" y: i32,\n" +"}\n" +"\n" +"// ANCHOR: Point-impl\n" +"impl Point {\n" +" // ANCHOR_END: Point-impl\n" +" pub fn new(x: i32, y: i32) -> Point {\n" +" Point { x, y }\n" +" }\n" +"\n" +" pub fn magnitude(self) -> f64 {\n" +" f64::from(self.x.pow(2) + self.y.pow(2)).sqrt()\n" +" }\n" +"\n" +" pub fn dist(self, other: Point) -> f64 {\n" +" (self - other).magnitude()\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Add for Point {\n" +" type Output = Self;\n" +"\n" +" fn add(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x + other.x,\n" +" y: self.y + other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"impl std::ops::Sub for Point {\n" +" type Output = Self;\n" +"\n" +" fn sub(self, other: Self) -> Self::Output {\n" +" Self {\n" +" x: self.x - other.x,\n" +" y: self.y - other.y,\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Polygon\n" +"pub struct Polygon {\n" +" // ANCHOR_END: Polygon\n" +" points: Vec,\n" +"}\n" +"\n" +"// ANCHOR: Polygon-impl\n" +"impl Polygon {\n" +" // ANCHOR_END: Polygon-impl\n" +" pub fn new() -> Polygon {\n" +" Polygon { points: Vec::new() }\n" +" }\n" +"\n" +" pub fn add_point(&mut self, point: Point) {\n" +" self.points.push(point);\n" +" }\n" +"\n" +" pub fn left_most_point(&self) -> Option {\n" +" self.points.iter().min_by_key(|p| p.x).copied()\n" +" }\n" +"\n" +" pub fn iter(&self) -> impl Iterator {\n" +" self.points.iter()\n" +" }\n" +"\n" +" pub fn length(&self) -> f64 {\n" +" if self.points.is_empty() {\n" +" return 0.0;\n" +" }\n" +"\n" +" let mut result = 0.0;\n" +" let mut last_point = self.points[0];\n" +" for point in &self.points[1..] {\n" +" result += last_point.dist(*point);\n" +" last_point = *point;\n" +" }\n" +" result += last_point.dist(self.points[0]);\n" +" result\n" +" // Alternatively, Iterator::zip() lets us iterate over the points as " +"pairs\n" +" // but we need to pair each point with the next one, and the last " +"point\n" +" // with the first point. The zip() iterator is finished as soon as " +"one of \n" +" // the source iterators is finished, a neat trick is to combine " +"Iterator::cycle\n" +" // with Iterator::skip to create the second iterator for the zip and " +"using map \n" +" // and sum to calculate the total length.\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Circle\n" +"pub struct Circle {\n" +" // ANCHOR_END: Circle\n" +" center: Point,\n" +" radius: i32,\n" +"}\n" +"\n" +"// ANCHOR: Circle-impl\n" +"impl Circle {\n" +" // ANCHOR_END: Circle-impl\n" +" pub fn new(center: Point, radius: i32) -> Circle {\n" +" Circle { center, radius }\n" +" }\n" +"\n" +" pub fn circumference(&self) -> f64 {\n" +" 2.0 * std::f64::consts::PI * f64::from(self.radius)\n" +" }\n" +"\n" +" pub fn dist(&self, other: &Self) -> f64 {\n" +" self.center.dist(other.center)\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: Shape\n" +"pub enum Shape {\n" +" Polygon(Polygon),\n" +" Circle(Circle),\n" +"}\n" +"// ANCHOR_END: Shape\n" +"\n" +"impl From for Shape {\n" +" fn from(poly: Polygon) -> Self {\n" +" Shape::Polygon(poly)\n" +" }\n" +"}\n" +"\n" +"impl From for Shape {\n" +" fn from(circle: Circle) -> Self {\n" +" Shape::Circle(circle)\n" +" }\n" +"}\n" +"\n" +"impl Shape {\n" +" pub fn perimeter(&self) -> f64 {\n" +" match self {\n" +" Shape::Polygon(poly) => poly.length(),\n" +" Shape::Circle(circle) => circle.circumference(),\n" +" }\n" +" }\n" +"}\n" +"\n" +"// ANCHOR: unit-tests\n" +"#[cfg(test)]\n" +"mod tests {\n" +" use super::*;\n" +"\n" +" fn round_two_digits(x: f64) -> f64 {\n" +" (x * 100.0).round() / 100.0\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_magnitude() {\n" +" let p1 = Point::new(12, 13);\n" +" assert_eq!(round_two_digits(p1.magnitude()), 17.69);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_dist() {\n" +" let p1 = Point::new(10, 10);\n" +" let p2 = Point::new(14, 13);\n" +" assert_eq!(round_two_digits(p1.dist(p2)), 5.00);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_point_add() {\n" +" let p1 = Point::new(16, 16);\n" +" let p2 = p1 + Point::new(-4, 3);\n" +" assert_eq!(p2, Point::new(12, 19));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_left_most_point() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +" assert_eq!(poly.left_most_point(), Some(p1));\n" +" }\n" +"\n" +" #[test]\n" +" fn test_polygon_iter() {\n" +" let p1 = Point::new(12, 13);\n" +" let p2 = Point::new(16, 16);\n" +"\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(p1);\n" +" poly.add_point(p2);\n" +"\n" +" let points = poly.iter().cloned().collect::>();\n" +" assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);\n" +" }\n" +"\n" +" #[test]\n" +" fn test_shape_perimeters() {\n" +" let mut poly = Polygon::new();\n" +" poly.add_point(Point::new(12, 13));\n" +" poly.add_point(Point::new(17, 11));\n" +" poly.add_point(Point::new(16, 16));\n" +" let shapes = vec![\n" +" Shape::from(poly),\n" +" Shape::from(Circle::new(Point::new(10, 20), 5)),\n" +" ];\n" +" let perimeters = shapes\n" +" .iter()\n" +" .map(Shape::perimeter)\n" +" .map(round_two_digits)\n" +" .collect::>();\n" +" assert_eq!(perimeters, vec![15.48, 31.42]);\n" +" }\n" +"}\n" +"// ANCHOR_END: unit-tests\n" +"\n" +"fn main() {}\n" +"```" +msgstr "" + #: src/exercises/day-3/solutions-afternoon.md:1 msgid "Day 3 Afternoon Exercises" msgstr "" @@ -19112,7 +20140,7 @@ msgid "" "mod ffi {\n" " use std::os::raw::{c_char, c_int};\n" " #[cfg(not(target_os = \"macos\"))]\n" -" use std::os::raw::{c_long, c_ulong, c_ushort};\n" +" use std::os::raw::{c_long, c_ulong, c_ushort, c_uchar};\n" "\n" " // Opaque type. See https://doc.rust-lang.org/nomicon/ffi.html.\n" " #[repr(C)]\n" @@ -19122,23 +20150,25 @@ msgid "" "PhantomPinned)>,\n" " }\n" "\n" -" // Layout as per readdir(3) and definitions in /usr/include/x86_64-linux-" -"gnu.\n" +" // Layout according to the Linux man page for readdir(3), where ino_t " +"and\n" +" // off_t are resolved according to the definitions in\n" +" // /usr/include/x86_64-linux-gnu/{sys/types.h, bits/typesizes.h}.\n" " #[cfg(not(target_os = \"macos\"))]\n" " #[repr(C)]\n" " pub struct dirent {\n" -" pub d_ino: c_long,\n" -" pub d_off: c_ulong,\n" +" pub d_ino: c_ulong,\n" +" pub d_off: c_long,\n" " pub d_reclen: c_ushort,\n" -" pub d_type: c_char,\n" +" pub d_type: c_uchar,\n" " pub d_name: [c_char; 256],\n" " }\n" "\n" -" // Layout as per man entry for dirent\n" -" #[cfg(target_os = \"macos\")]\n" +" // Layout according to the macOS man page for dir(5).\n" +" #[cfg(all(target_os = \"macos\"))]\n" " #[repr(C)]\n" " pub struct dirent {\n" -" pub d_ino: u64,\n" +" pub d_fileno: u64,\n" " pub d_seekoff: u64,\n" " pub d_reclen: u16,\n" " pub d_namlen: u16,\n" @@ -19148,7 +20178,22 @@ msgid "" "\n" " extern \"C\" {\n" " pub fn opendir(s: *const c_char) -> *mut DIR;\n" +"\n" +" #[cfg(not(all(target_os = \"macos\", target_arch = \"x86_64\")))]\n" " pub fn readdir(s: *mut DIR) -> *const dirent;\n" +"\n" +" // See https://github.com/rust-lang/libc/issues/414 and the section " +"on\n" +" // _DARWIN_FEATURE_64_BIT_INODE in the macOS man page for stat(2).\n" +" //\n" +" // \"Platforms that existed before these updates were available\" " +"refers\n" +" // to macOS (as opposed to iOS / wearOS / etc.) on Intel and " +"PowerPC.\n" +" #[cfg(all(target_os = \"macos\", target_arch = \"x86_64\"))]\n" +" #[link_name = \"readdir$INODE64\"]\n" +" pub fn readdir(s: *mut DIR) -> *const dirent;\n" +"\n" " pub fn closedir(s: *mut DIR) -> c_int;\n" " }\n" "}\n" @@ -19697,8 +20742,8 @@ msgid "" "\n" " /// Returns whether there is currently an interrupt pending.\n" " ///\n" -" /// This should be true iff `matched` returns true and the interrupt is\n" -" /// masked.\n" +" /// This should be true if and only if `matched` returns true and the\n" +" /// interrupt is masked.\n" " pub fn interrupt_pending(&self) -> bool {\n" " // Safe because we know that self.registers points to the control\n" " // registers of a PL031 device which is appropriately mapped.\n" @@ -19809,8 +20854,8 @@ msgid "" "\n" " for i in 0..forks.len() {\n" " let tx = tx.clone();\n" -" let mut left_fork = forks[i].clone();\n" -" let mut right_fork = forks[(i + 1) % forks.len()].clone();\n" +" let mut left_fork = Arc::clone(&forks[i]);\n" +" let mut right_fork = Arc::clone(&forks[(i + 1) % forks.len()]);\n" "\n" " // To avoid a deadlock, we have to break the symmetry\n" " // somewhere. This will swap the forks without deinitializing\n" @@ -19842,6 +20887,210 @@ msgid "" "```" msgstr "" +#: src/exercises/concurrency/solutions-morning.md:104 +#, fuzzy +msgid "Link Checker" +msgstr "マルチスレッド・リンクチェッカー" + +#: src/exercises/concurrency/solutions-morning.md:106 +msgid "([back to exercise](link-checker.md))" +msgstr "" + +#: src/exercises/concurrency/solutions-morning.md:108 +msgid "" +"```rust,compile_fail\n" +"// Copyright 2022 Google LLC\n" +"//\n" +"// Licensed under the Apache License, Version 2.0 (the \"License\");\n" +"// you may not use this file except in compliance with the License.\n" +"// You may obtain a copy of the License at\n" +"//\n" +"// http://www.apache.org/licenses/LICENSE-2.0\n" +"//\n" +"// Unless required by applicable law or agreed to in writing, software\n" +"// distributed under the License is distributed on an \"AS IS\" BASIS,\n" +"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +"// See the License for the specific language governing permissions and\n" +"// limitations under the License.\n" +"\n" +"use std::{sync::Arc, sync::Mutex, sync::mpsc, thread};\n" +"\n" +"// ANCHOR: setup\n" +"use reqwest::{blocking::Client, Url};\n" +"use scraper::{Html, Selector};\n" +"use thiserror::Error;\n" +"\n" +"#[derive(Error, Debug)]\n" +"enum Error {\n" +" #[error(\"request error: {0}\")]\n" +" ReqwestError(#[from] reqwest::Error),\n" +" #[error(\"bad http response: {0}\")]\n" +" BadResponse(String),\n" +"}\n" +"// ANCHOR_END: setup\n" +"\n" +"// ANCHOR: visit_page\n" +"#[derive(Debug)]\n" +"struct CrawlCommand {\n" +" url: Url,\n" +" extract_links: bool,\n" +"}\n" +"\n" +"fn visit_page(client: &Client, command: &CrawlCommand) -> Result, " +"Error> {\n" +" println!(\"Checking {:#}\", command.url);\n" +" let response = client.get(command.url.clone()).send()?;\n" +" if !response.status().is_success() {\n" +" return Err(Error::BadResponse(response.status().to_string()));\n" +" }\n" +"\n" +" let mut link_urls = Vec::new();\n" +" if !command.extract_links {\n" +" return Ok(link_urls);\n" +" }\n" +"\n" +" let base_url = response.url().to_owned();\n" +" let body_text = response.text()?;\n" +" let document = Html::parse_document(&body_text);\n" +"\n" +" let selector = Selector::parse(\"a\").unwrap();\n" +" let href_values = document\n" +" .select(&selector)\n" +" .filter_map(|element| element.value().attr(\"href\"));\n" +" for href in href_values {\n" +" match base_url.join(href) {\n" +" Ok(link_url) => {\n" +" link_urls.push(link_url);\n" +" }\n" +" Err(err) => {\n" +" println!(\"On {base_url:#}: ignored unparsable {href:?}: " +"{err}\");\n" +" }\n" +" }\n" +" }\n" +" Ok(link_urls)\n" +"}\n" +"// ANCHOR_END: visit_page\n" +"\n" +"struct CrawlState {\n" +" domain: String,\n" +" visited_pages: std::collections::HashSet,\n" +"}\n" +"\n" +"impl CrawlState {\n" +" fn new(start_url: &Url) -> CrawlState {\n" +" let mut visited_pages = std::collections::HashSet::new();\n" +" visited_pages.insert(start_url.as_str().to_string());\n" +" CrawlState {\n" +" domain: start_url.domain().unwrap().to_string(),\n" +" visited_pages,\n" +" }\n" +" }\n" +"\n" +" /// Determine whether links within the given page should be extracted.\n" +" fn should_extract_links(&self, url: &Url) -> bool {\n" +" let Some(url_domain) = url.domain() else {\n" +" return false;\n" +" };\n" +" url_domain == self.domain\n" +" }\n" +"\n" +" /// Mark the given page as visited, returning true if it had already\n" +" /// been visited.\n" +" fn mark_visited(&mut self, url: &Url) -> bool {\n" +" self.visited_pages.insert(url.as_str().to_string())\n" +" }\n" +"}\n" +"\n" +"type CrawlResult = Result, (Url, Error)>;\n" +"fn spawn_crawler_threads(\n" +" command_receiver: mpsc::Receiver,\n" +" result_sender: mpsc::Sender,\n" +" thread_count: u32,\n" +") {\n" +" let command_receiver = Arc::new(Mutex::new(command_receiver));\n" +"\n" +" for _ in 0..thread_count {\n" +" let result_sender = result_sender.clone();\n" +" let command_receiver = command_receiver.clone();\n" +" thread::spawn(move || {\n" +" let client = Client::new();\n" +" loop {\n" +" let command_result = {\n" +" let receiver_guard = command_receiver.lock().unwrap();\n" +" receiver_guard.recv()\n" +" };\n" +" let Ok(crawl_command) = command_result else {\n" +" // The sender got dropped. No more commands coming in.\n" +" break;\n" +" };\n" +" let crawl_result = match visit_page(&client, &crawl_command) " +"{\n" +" Ok(link_urls) => Ok(link_urls),\n" +" Err(error) => Err((crawl_command.url, error)),\n" +" };\n" +" result_sender.send(crawl_result).unwrap();\n" +" }\n" +" });\n" +" }\n" +"}\n" +"\n" +"fn control_crawl(\n" +" start_url: Url,\n" +" command_sender: mpsc::Sender,\n" +" result_receiver: mpsc::Receiver,\n" +") -> Vec {\n" +" let mut crawl_state = CrawlState::new(&start_url);\n" +" let start_command = CrawlCommand { url: start_url, extract_links: " +"true };\n" +" command_sender.send(start_command).unwrap();\n" +" let mut pending_urls = 1;\n" +"\n" +" let mut bad_urls = Vec::new();\n" +" while pending_urls > 0 {\n" +" let crawl_result = result_receiver.recv().unwrap();\n" +" pending_urls -= 1;\n" +"\n" +" match crawl_result {\n" +" Ok(link_urls) => {\n" +" for url in link_urls {\n" +" if crawl_state.mark_visited(&url) {\n" +" let extract_links = crawl_state." +"should_extract_links(&url);\n" +" let crawl_command = CrawlCommand { url, " +"extract_links };\n" +" command_sender.send(crawl_command).unwrap();\n" +" pending_urls += 1;\n" +" }\n" +" }\n" +" }\n" +" Err((url, error)) => {\n" +" bad_urls.push(url);\n" +" println!(\"Got crawling error: {:#}\", error);\n" +" continue;\n" +" }\n" +" }\n" +" }\n" +" bad_urls\n" +"}\n" +"\n" +"fn check_links(start_url: Url) -> Vec {\n" +" let (result_sender, result_receiver) = mpsc::channel::();\n" +" let (command_sender, command_receiver) = mpsc::channel::" +"();\n" +" spawn_crawler_threads(command_receiver, result_sender, 16);\n" +" control_crawl(start_url, command_sender, result_receiver)\n" +"}\n" +"\n" +"fn main() {\n" +" let start_url = reqwest::Url::parse(\"https://www.google.org\")." +"unwrap();\n" +" let bad_urls = check_links(start_url);\n" +" println!(\"Bad URLs: {:#?}\", bad_urls);\n" +"}\n" +"```" +msgstr "" + #: src/exercises/concurrency/solutions-afternoon.md:1 msgid "Concurrency Afternoon Exercise" msgstr "" @@ -19930,14 +21179,19 @@ msgid "" " let mut philosophers = vec![];\n" " let (tx, rx) = mpsc::channel(10);\n" " for (i, name) in PHILOSOPHERS.iter().enumerate() {\n" -" let left_fork = forks[i].clone();\n" -" let right_fork = forks[(i + 1) % PHILOSOPHERS.len()].clone();\n" +" let left_fork = Arc::clone(&forks[i]);\n" +" let right_fork = Arc::clone(&forks[(i + 1) % PHILOSOPHERS." +"len()]);\n" +" // To avoid a deadlock, we have to break the symmetry\n" +" // somewhere. This will swap the forks without deinitializing\n" +" // either of them.\n" +" if i == 0 {\n" +" std::mem::swap(&mut left_fork, &mut right_fork);\n" +" }\n" " philosophers.push(Philosopher {\n" " name: name.to_string(),\n" -" left_fork: if i % 2 == 0 { left_fork.clone() } else " -"{ right_fork.clone() },\n" -" right_fork: if i % 2 == 0 { right_fork } else " -"{ left_fork },\n" +" left_fork,\n" +" right_fork,\n" " thoughts: tx.clone(),\n" " });\n" " }\n" @@ -19964,11 +21218,11 @@ msgid "" "```" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md:115 +#: src/exercises/concurrency/solutions-afternoon.md:121 msgid "([back to exercise](chat-app.md))" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md:119 +#: src/exercises/concurrency/solutions-afternoon.md:125 msgid "" "```rust,compile_fail\n" "// Copyright 2023 Google LLC\n" @@ -20055,7 +21309,7 @@ msgid "" "```" msgstr "" -#: src/exercises/concurrency/solutions-afternoon.md:204 +#: src/exercises/concurrency/solutions-afternoon.md:210 msgid "" "```rust,compile_fail\n" "// Copyright 2023 Google LLC\n" @@ -20086,12 +21340,11 @@ msgid "" " .await?;\n" "\n" " let stdin = tokio::io::stdin();\n" -" let mut stdin = BufReader::new(stdin);\n" +" let mut stdin = BufReader::new(stdin).lines();\n" "\n" " // ANCHOR_END: setup\n" " // Continuous loop for concurrently sending and receiving messages.\n" " loop {\n" -" let mut line = String::new();\n" " tokio::select! {\n" " incoming = ws_stream.next() => {\n" " match incoming {\n" @@ -20101,10 +21354,10 @@ msgid "" " None => return Ok(()),\n" " }\n" " }\n" -" res = stdin.read_line(&mut line) => {\n" +" res = stdin.next_line() => {\n" " match res {\n" -" Ok(0) => return Ok(()),\n" -" Ok(_) => ws_stream.send(Message::text(line.trim_end()." +" Ok(None) => return Ok(()),\n" +" Ok(Some(line)) => ws_stream.send(Message::text(line." "to_string())).await?,\n" " Err(err) => return Err(err.into()),\n" " }\n" @@ -20115,3 +21368,53 @@ msgid "" "}\n" "```" msgstr "" + +#~ msgid "" +#~ "[![GitHub contributors](https://img.shields.io/github/contributors/google/" +#~ "comprehensive-rust?style=flat-square)](https://github.com/google/" +#~ "comprehensive-rust/graphs/contributors) [![GitHub stars](https://img." +#~ "shields.io/github/stars/google/comprehensive-rust?style=flat-square)]" +#~ "(https://github.com/google/comprehensive-rust/stargazers)" +#~ msgstr "" +#~ "[![GitHub contributors](https://img.shields.io/github/contributors/google/" +#~ "comprehensive-rust?style=flat-square)](https://github.com/google/" +#~ "comprehensive-rust/graphs/contributors) [![GitHub stars](https://img." +#~ "shields.io/github/stars/google/comprehensive-rust?style=flat-square)]" +#~ "(https://github.com/google/comprehensive-rust/stargazers)" + +#~ msgid "" +#~ "[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" +#~ "rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +#~ "stargazers)" +#~ msgstr "" +#~ "[![GitHub stars](https://img.shields.io/github/stars/google/comprehensive-" +#~ "rust?style=flat-square)](https://github.com/google/comprehensive-rust/" +#~ "stargazers)" + +#~ msgid "Day 1: Basic Rust, ownership and the borrow checker." +#~ msgstr "Day 1: Rustの基本、所有権と借用チェッカー" + +#~ msgid "Concurrency" +#~ msgstr "並行性" + +#~ msgid "Rustup (Recommended)" +#~ msgstr "Rustup (推奨)" + +#~ msgid "" +#~ "You can follow the instructions to install cargo and rust compiler, among " +#~ "other standard ecosystem tools with the [rustup](https://rust-analyzer." +#~ "github.io/) tool, which is maintained by the Rust Foundation." +#~ msgstr "" +#~ "[rustup](https://rust-analyzer.github.io/)ツールを使用して、cargoやrustコ" +#~ "ンパイラなどの標準エコシステムツールをインストールします。RustupはRust " +#~ "Foundationによってメンテナンスされています。" + +#~ msgid "Package Managers" +#~ msgstr "パッケージマネージャ" + +#~ msgid "" +#~ "Runtimes have the concept of a \"task\", similar to a thread but much " +#~ "less resource-intensive." +#~ msgstr "" +#~ "ランタイムには「タスク」という概念があり、スレッドに似ているものの、スレッ" +#~ "ドよりリソースの消費ははるかに小さいです。"