This commit is contained in:
TimLai666 2024-06-15 23:48:04 +08:00 committed by GitHub
parent 49a9f823c8
commit a3043adc54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 58 additions and 87 deletions

View File

@ -4,6 +4,6 @@
一旦一個值被綁定到一個名稱,你就不能改變這個值。
你可以通過在變數名稱前面添加 `mut` 使其變為可變的。
## 更多資訊
## 進一步了解
- [變數和可變性](https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html)

View File

@ -2,6 +2,6 @@
在這裡,您將學習如何編寫函數以及 Rust 編譯器如何幫助您調試debug錯誤即使是更複雜的代碼中的。
## 更多資訊
## 進一步了解
- [函數如何運作](https://doc.rust-lang.org/book/ch03-03-how-functions-work.html)

View File

@ -2,6 +2,6 @@
`if` 是最基本(但仍然非常多用途!)的控制流類型,您將在這裡學習它。
## 更多資訊
## 進一步了解
- [控制流 - if 表達式](https://doc.rust-lang.org/book/ch03-05-control-flow.html#if-expressions)

View File

@ -2,7 +2,7 @@
Rust 有幾種基本類型是直接由編譯器實現的。在這一部分,我們將介紹最重要的那些。
## 更多資訊
## 進一步了解
- [資料型態](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html)
- [切片類型](https://doc.rust-lang.org/stable/book/ch04-03-slices.html)

View File

@ -4,7 +4,7 @@
向量在書中屬於稍後的章節,但我們認為它們足夠有用,值得提前介紹。我們將在後面討論另一個有用的資料結構:雜湊表。
## 更多資訊
## 進一步了解
- [使用向量存儲值列表](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html)
- [`iter_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.iter_mut)

View File

@ -2,7 +2,7 @@
這些練習改編自 [pnkfelix](https://github.com/pnkfelix) 的 [Rust Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) ——感謝 Felix
## 更多資訊
## 進一步了解
在這一部分中的連結特別重要。

View File

@ -2,7 +2,7 @@
Rust 有三種結構體類型:經典 C 結構體、元組結構體和單元結構體。
## 更多資訊
## 進一步了解
- [結構體](https://doc.rust-lang.org/book/ch05-01-defining-structs.html)
- [方法語法](https://doc.rust-lang.org/book/ch05-03-method-syntax.html)

View File

@ -4,7 +4,7 @@ Rust 允許您定義稱為 "枚舉" 的類型,這些類型列舉了可能的
枚舉是許多語言中的一個特性但其能力在每種語言中都有所不同。Rust 的枚舉最類似於函數式語言中的代數數據類型,例如 F#、OCaml 和 Haskell。
與枚舉結合使用的有用特性是 Rust 的 "模式匹配" 功能,這使得對枚舉的不同值運行不同代碼變得容易。
## 更多資訊
## 進一步了解
- [枚舉](https://doc.rust-lang.org/book/ch06-00-enums.html)
- [模式語法](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html)

View File

@ -3,6 +3,6 @@
Rust 有兩種類型的字串:字串切片 (`&str`) 和 owned string (`String`)。
我們不會規定您應該何時使用哪一種,但我們會向您展示如何識別和創建它們,以及如何使用它們。
## 更多資訊
## 進一步了解
- [字串](https://doc.rust-lang.org/book/ch08-02-strings.html)

View File

@ -2,6 +2,6 @@
在本節中,我們將向您介紹 Rust 的模組系統。
## 更多資訊
## 進一步了解
- [模組系統](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html)

View File

@ -5,6 +5,6 @@
這是我們之前談論 Vecs 時提到的另一個資料結構。
## 更多資訊
## 進一步了解
- [在雜湊表中存儲鍵和值](https://doc.rust-lang.org/book/ch08-03-hash-maps.html)

View File

@ -12,7 +12,7 @@
- 可空指針
- 將複雜的事情變簡單
## 更多資訊
## 進一步了解
- [Option 枚舉格式](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-enum-definitions)
- [Option 模組文檔](https://doc.rust-lang.org/std/option/)

View File

@ -1,12 +1,10 @@
# Error handling
# 錯誤處理
Most errors arent serious enough to require the program to stop entirely.
Sometimes, when a function fails, its for a reason that you can easily interpret and respond to.
For example, if you try to open a file and that operation fails because the file doesnt exist, you might want to create the file instead of terminating the process.
大多數錯誤不會嚴重到需要程式完全停止。有時候,當一個函數發生錯誤時,原因可能很容易理解並能夠應對。例如,如果您嘗試打開一個檔案,但操作失敗是因為該檔案不存在,您可能希望建立該檔案,而不是終止進程。
## Further information
## 進一步了解
- [Error Handling](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html)
- [Generics](https://doc.rust-lang.org/book/ch10-01-syntax.html)
- [錯誤處理](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html)
- [泛型](https://doc.rust-lang.org/book/ch10-01-syntax.html)
- [Result](https://doc.rust-lang.org/rust-by-example/error/result.html)
- [Boxing errors](https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/boxing_errors.html)
- [包裝錯誤](https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/boxing_errors.html)

View File

@ -1,19 +1,16 @@
// errors1.rs
//
// This function refuses to generate text to be printed on a nametag if you pass
// it an empty string. It'd be nicer if it explained what the problem was,
// instead of just sometimes returning `None`. Thankfully, Rust has a similar
// construct to `Option` that can be used to express error conditions. Let's use
// it!
// 如果您傳遞一個空字符串,此函數將拒絕生成要印在名牌上的文本。
// 如果它能解釋一下問題所在而不是只返回 `None` 會更好。
// 幸運的是Rust 有一個類似於 `Option` 的結構可以用來表達錯誤情況。讓我們來使用它!
//
// Execute `rustlings hint errors1` or use the `hint` watch subcommand for a
// hint.
// 執行 `rustlings hint errors1` 或使用 `hint` watch 子命令來獲取提示。
// I AM NOT DONE
pub fn generate_nametag_text(name: String) -> Option<String> {
if name.is_empty() {
// Empty names aren't allowed.
// 不允許空名字。
None
} else {
Some(format!("Hi! My name is {}", name))
@ -36,7 +33,7 @@ mod tests {
fn explains_why_generating_nametag_text_fails() {
assert_eq!(
generate_nametag_text("".into()),
// Don't change this line
// 不要更改這一行
Err("`name` was empty; it must be nonempty.".into())
);
}

View File

@ -1,23 +1,16 @@
// errors2.rs
//
// Say we're writing a game where you can buy items with tokens. All items cost
// 5 tokens, and whenever you purchase items there is a processing fee of 1
// token. A player of the game will type in how many items they want to buy, and
// the `total_cost` function will calculate the total cost of the items. Since
// the player typed in the quantity, though, we get it as a string-- and they
// might have typed anything, not just numbers!
// 假設我們在編寫一個可以用代幣購買物品的遊戲。所有物品的價格都是 5 個代幣,並且每次購買物品時都有 1 個代幣的處理費用。
// 遊戲玩家會輸入他們想購買的物品數量,而 `total_cost` 函數將計算物品的總成本。
// 由於玩家輸入的是數量,所以我們得到的是一個字串 —— 他們可能輸入了任何東西,不僅僅是數字!
//
// Right now, this function isn't handling the error case at all (and isn't
// handling the success case properly either). What we want to do is: if we call
// the `total_cost` function on a string that is not a number, that function
// will return a `ParseIntError`, and in that case, we want to immediately
// return that error from our function and not try to multiply and add.
// 現在,這個函數根本沒有處理錯誤情況(並且也沒有正確處理成功情況)。
// 我們想要的是:如果我們在一個不是數字的字符串上調用 `total_cost` 函數,那麼該函數將返回一個 `ParseIntError`
// 在這種情況下,我們希望立即從我們的函數返回該錯誤,而不是嘗試進行乘法和加法。
//
// There are at least two ways to implement this that are both correct-- but one
// is a lot shorter!
// 至少有兩種實現方法都是正確的 —— 但其中一種要短得多!
//
// Execute `rustlings hint errors2` or use the `hint` watch subcommand for a
// hint.
// 執行 `rustlings hint errors2` 或使用 `hint` watch 子命令來獲取提示。
// I AM NOT DONE

View File

@ -1,11 +1,9 @@
// errors3.rs
//
// This is a program that is trying to use a completed version of the
// `total_cost` function from the previous exercise. It's not working though!
// Why not? What should we do to fix it?
// 這是一個試圖使用前一個練習中完成的 `total_cost` 函數的程序。但它不起作用!
// 為什麼不行?我們應該怎麼做才能修復它?
//
// Execute `rustlings hint errors3` or use the `hint` watch subcommand for a
// hint.
// 執行 `rustlings hint errors3` 或使用 `hint` watch 子命令來獲取提示。
// I AM NOT DONE
@ -18,10 +16,10 @@ fn main() {
let cost = total_cost(pretend_user_input)?;
if cost > tokens {
println!("You can't afford that many!");
println!("您買不起!");
} else {
tokens -= cost;
println!("You now have {} tokens.", tokens);
println!("您現在有 {} 個代幣。", tokens);
}
}

View File

@ -1,7 +1,6 @@
// errors4.rs
//
// Execute `rustlings hint errors4` or use the `hint` watch subcommand for a
// hint.
// 執行 `rustlings hint errors4` 或使用 `hint` watch 子命令來獲取提示。
// I AM NOT DONE
@ -16,7 +15,7 @@ enum CreationError {
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
// Hmm... Why is this always returning an Ok value?
// Hmm... 為什麼這裡總是返回 Ok 值呢?
Ok(PositiveNonzeroInteger(value as u64))
}
}

View File

@ -1,26 +1,17 @@
// errors5.rs
//
// This program uses an altered version of the code from errors4.
// 此程式使用了一個從 errors4 中修改的代碼。
//
// This exercise uses some concepts that we won't get to until later in the
// course, like `Box` and the `From` trait. It's not important to understand
// them in detail right now, but you can read ahead if you like. For now, think
// of the `Box<dyn ???>` type as an "I want anything that does ???" type, which,
// given Rust's usual standards for runtime safety, should strike you as
// somewhat lenient!
// 本練習使用了一些我們要到課程後面才會涉及的概念,比如 `Box` 和 `From` 特徵。
// 現在並不需要詳細了解它們,但如果您願意,可以提前閱讀。現在,將 `Box<dyn ???>` 類型看作是一種“我想要實現 ??? 的任何類型”的類型,
// 考慮到 Rust 的常規運行時安全標準,這應該讓您感到有些寬鬆!
//
// In short, this particular use case for boxes is for when you want to own a
// value and you care only that it is a type which implements a particular
// trait. To do so, The Box is declared as of type Box<dyn Trait> where Trait is
// the trait the compiler looks for on any value used in that context. For this
// exercise, that context is the potential errors which can be returned in a
// Result.
// 簡而言之,這個 Box 的特定用例是當您想要擁有一個值並且只關心它是一個實現特定特徵的類型時。為此Box 被聲明為 Box<dyn Trait> 類型,
// 其中 Trait 是編譯器在該上下文中使用的任何值上查找的特徵。對於本練習,該上下文是可能在 Result 中返回的錯誤。
//
// What can we use to describe both errors? In other words, is there a trait
// which both errors implement?
// 我們可以用什麼來描述這兩個錯誤?換句話說,有沒有一個兩個錯誤都實現的特徵?
//
// Execute `rustlings hint errors5` or use the `hint` watch subcommand for a
// hint.
// 執行 `rustlings hint errors5` 或使用 `hint` watch 子命令來獲取提示。
// I AM NOT DONE
@ -28,7 +19,7 @@ use std::error;
use std::fmt;
use std::num::ParseIntError;
// TODO: update the return type of `main()` to make this compile.
// TODO: 更新 `main()` 的返回類型以使其編譯。
fn main() -> Result<(), Box<dyn ???>> {
let pretend_user_input = "42";
let x: i64 = pretend_user_input.parse()?;
@ -36,7 +27,7 @@ fn main() -> Result<(), Box<dyn ???>> {
Ok(())
}
// Don't change anything below this line.
// 不要更改此行以下的任何內容。
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
@ -57,7 +48,7 @@ impl PositiveNonzeroInteger {
}
}
// This is required so that `CreationError` can implement `error::Error`.
// 這是 `CreationError` 實現 `error::Error` 所需要的。
impl fmt::Display for CreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let description = match *self {

View File

@ -1,19 +1,15 @@
// errors6.rs
//
// Using catch-all error types like `Box<dyn error::Error>` isn't recommended
// for library code, where callers might want to make decisions based on the
// error content, instead of printing it out or propagating it further. Here, we
// define a custom error type to make it possible for callers to decide what to
// do next when our function returns an error.
// 不建議在庫代碼中使用 `Box<dyn error::Error>` 這樣的通用錯誤類型,因為調用者可能希望根據錯誤內容做出決策,而不是印出來或進一步傳播錯誤。
// 在這裡,我們定義了一個自定義錯誤類型,使得當我們的函數回傳錯誤時,調用者可以決定接下來的操作。
//
// Execute `rustlings hint errors6` or use the `hint` watch subcommand for a
// hint.
// 執行 `rustlings hint errors6` 或使用 `hint` watch 子命令來獲取提示。
// I AM NOT DONE
use std::num::ParseIntError;
// This is a custom error type that we will be using in `parse_pos_nonzero()`.
// 這是一個我們將在 `parse_pos_nonzero()` 中使用的自定義錯誤類型。
#[derive(PartialEq, Debug)]
enum ParsePosNonzeroError {
Creation(CreationError),
@ -24,18 +20,17 @@ impl ParsePosNonzeroError {
fn from_creation(err: CreationError) -> ParsePosNonzeroError {
ParsePosNonzeroError::Creation(err)
}
// TODO: add another error conversion function here.
// TODO: 在這裡添加另一個錯誤轉換函數。
// fn from_parseint...
}
fn parse_pos_nonzero(s: &str) -> Result<PositiveNonzeroInteger, ParsePosNonzeroError> {
// TODO: change this to return an appropriate error instead of panicking
// when `parse()` returns an error.
// TODO: 修改這裡以返回合適的錯誤,而不是在 `parse()` 返回錯誤時崩潰。
let x: i64 = s.parse().unwrap();
PositiveNonzeroInteger::new(x).map_err(ParsePosNonzeroError::from_creation)
}
// Don't change anything below this line.
// 不要更改此行以下的任何內容。
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
@ -62,7 +57,7 @@ mod test {
#[test]
fn test_parse_error() {
// We can't construct a ParseIntError, so we have to pattern match.
// 我們無法構造 ParseIntError因此我們必須進行模式匹配。
assert!(matches!(
parse_pos_nonzero("not a number"),
Err(ParsePosNonzeroError::ParseInt(_))