diff --git a/listings/ch20-web-server/listing-20-14/src/lib.rs b/listings/ch20-web-server/listing-20-14/src/lib.rs index 23e06801..06dece6f 100644 --- a/listings/ch20-web-server/listing-20-14/src/lib.rs +++ b/listings/ch20-web-server/listing-20-14/src/lib.rs @@ -22,7 +22,7 @@ impl ThreadPool { let mut threads = Vec::with_capacity(size); for _ in 0..size { - // 就產生些執行緒並儲存至向量 + // 將產生些執行緒並儲存至向量 } ThreadPool { threads } diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 33251ad0..41795ac2 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -84,7 +84,7 @@ - [發佈 Crate 到 Crates.io](ch14-02-publishing-to-crates-io.md) - [Cargo 工作空間](ch14-03-cargo-workspaces.md) - [透過 `cargo install` 安裝執行檔](ch14-04-installing-binaries.md) - - [透過自訂命命來擴展 Cargo 的功能](ch14-05-extending-cargo.md) + - [透過自訂命令來擴展 Cargo 的功能](ch14-05-extending-cargo.md) - [智慧指標](ch15-00-smart-pointers.md) - [使用 `Box` 指向堆積上的資料](ch15-01-box.md) diff --git a/src/ch03-01-variables-and-mutability.md b/src/ch03-01-variables-and-mutability.md index 9dc195ea..a0bad159 100644 --- a/src/ch03-01-variables-and-mutability.md +++ b/src/ch03-01-variables-and-mutability.md @@ -58,7 +58,7 @@ const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3; ``` -變數的名稱為 `THREE_HOURS_IN_SECONDS` ,且它的數值被設為 60(一分鐘有多少秒)乘上 60(一小時有多少分鐘)乘上 3(此程式想要計算的小時數量)。Rust 的常數命名規則為使用全部英文大寫並用底寫區隔每個單字。編譯器能夠在編譯時用特定限制集合內的操作進行運算,讓我們能用易於理解且驗證的方式寫出此數值,而不用將常數設爲 10,800。你可以查閱 Rust Reference 的 [constant evaluation 段落][const-eval]來瞭解哪些操作可以在宣告常數時使用。 +變數的名稱為 `THREE_HOURS_IN_SECONDS` ,且它的數值被設為 60(一分鐘有多少秒)乘上 60(一小時有多少分鐘)乘上 3(此程式想要計算的小時數量)。Rust 的常數命名規則為使用全部英文大寫並用底線區隔每個單字。編譯器能夠在編譯時用特定限制集合內的操作進行運算,讓我們能用易於理解且驗證的方式寫出此數值,而不用將常數設爲 10,800。你可以查閱 Rust Reference 的 [constant evaluation 段落][const-eval]來瞭解哪些操作可以在宣告常數時使用。 在整支程式運行時,常數在它們的範圍內都是有效的。這樣的性質讓常數在處理應用程式中需要被許多程式碼部份所知道的數值的情況下是非常好的選擇,像是一款遊戲中玩家能夠得到的最高分數或者光速的數值。 diff --git a/src/ch03-04-comments.md b/src/ch03-04-comments.md index 81df6024..58396c1f 100644 --- a/src/ch03-04-comments.md +++ b/src/ch03-04-comments.md @@ -12,7 +12,7 @@ ```rust // 這邊處理的事情很複雜,長到 -// 我們需要多行註解來能解釋! +// 我們需要多行註解來解釋! // 希望此註解能幫助你理解。 ``` @@ -34,4 +34,4 @@ Rust 還有另一種註解:技術文件註解。我們會在第十四章的[「發佈 Crate 到 Crates.io」][publishing]段落提到它。 -[publishing]: ch14-02-publishing-to-crates-io.html \ No newline at end of file +[publishing]: ch14-02-publishing-to-crates-io.html diff --git a/src/ch03-05-control-flow.md b/src/ch03-05-control-flow.md index 392d89e7..b8396428 100644 --- a/src/ch03-05-control-flow.md +++ b/src/ch03-05-control-flow.md @@ -36,7 +36,7 @@ {{#include ../listings/ch03-common-programming-concepts/no-listing-27-if-false/output.txt}} ``` -還有一件值得注意的是程式碼的條件判斷**必須**是 `bool`。如果條件不是 `bool` 的話,我們就會遇到錯誤。比方說,試試以下程式碼: +還有一點值得注意的是程式碼的條件判斷**必須**是 `bool`。如果條件不是 `bool` 的話,我們就會遇到錯誤。比方說,試試以下程式碼: 檔案名稱:src/main.rs diff --git a/src/ch07-01-packages-and-crates.md b/src/ch07-01-packages-and-crates.md index fddfb335..6b5c3a98 100644 --- a/src/ch07-01-packages-and-crates.md +++ b/src/ch07-01-packages-and-crates.md @@ -8,7 +8,7 @@ **函式庫(Library)crate** 則不會有 `main` 函式,而且它們也不會編譯成執行檔。這種 crate 定義的功能用來分享給多重專案使用。舉例來說,我們在[第二章][rand]用到的 `rand` crate 就提供了產生隨機數值的功能。當大多數的 Rustacean 講到「crate」時,他們其實指的是函式庫 crate,所以他們講到「crate」時相當於就是在講其他程式語言概念中的「函式庫」。 -**crate 的源頭**會是一個原始檔案,讓 Rust 的編譯器可以作為起始點並組織 crate 模組的地方(我們會在[「定義模組來控制作用域與隱私權」][modules]的段落更加解釋模組)。 +**crate 的源頭**會是一個原始檔案,讓 Rust 的編譯器可以作為起始點並組織 crate 模組的地方(我們會在[「定義模組來控制作用域與隱私權」][modules]的段落詳加解釋模組)。 **套件**(package)則是提供一系列功能的一或數個 crate。一個套件會包含一個 *Cargo.toml* 檔案來解釋如何建構那些 crate。Cargo 本身其實就是個套件,包含了你已經用來建構程式碼的命令列工具。Cargo 套件還包含執行檔 crate 需要依賴的函式庫 crate。其他專案可以依賴 Cargo 函式庫來使用與 Cargo 命令列工具用到的相同邏輯功能。 diff --git a/src/ch07-02-defining-modules-to-control-scope-and-privacy.md b/src/ch07-02-defining-modules-to-control-scope-and-privacy.md index 42bffa22..61c374ac 100644 --- a/src/ch07-02-defining-modules-to-control-scope-and-privacy.md +++ b/src/ch07-02-defining-modules-to-control-scope-and-privacy.md @@ -6,7 +6,7 @@ ### 模組懶人包 -這裡我們先快速帶過模組、路徑、`use` 關鍵字以及 `pub` 關鍵字在編譯器中是怎麼運作的,以及多數開發者會怎麼組織他們的程式碼。我們會在此章節透過範例逐依介紹,不過這裡能讓你快速理解模組是怎麼運作的。 +這裡我們先快速帶過模組、路徑、`use` 關鍵字以及 `pub` 關鍵字在編譯器中是怎麼運作的,以及多數開發者會怎麼組織他們的程式碼。我們會在此章節透過範例逐一介紹,不過這裡能讓你快速理解模組是怎麼運作的。 - **從 crate 源頭開始**:在編譯 crate 時,編譯器會先尋找 crate 源頭檔案(函式庫 crate 的話,通常就是 *src/lib.rs*;執行檔 crate 的話,通常就是 *src/main.rs*)來編譯程式碼。 - **宣告模組**:在 crate 源頭檔案中,你可以宣告新的模組,比如說你宣告了一個「garden」模組 `mod garden;`。編譯器會在以下這幾處尋找模組的程式碼: diff --git a/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md b/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md index 89473dbe..aa58b5c9 100644 --- a/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md +++ b/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md @@ -63,7 +63,7 @@ Rust 選擇這樣的模組系統,讓內部實作細節預設都是隱藏起來 範例 7-6:編譯範例 7-5 時產生的錯誤 -到底發生了什麼事?在 `mod hosting` 之前加上 `pub` 關鍵字確實公開了模組。有了這項修改後,我們的確可以在取得 `front_of_house` 的後繼續進入 `hosting`。但是 `hosting` 的所有**內容**仍然是私有的。模組中的 `pub` 關鍵字只會讓該模組公開讓上層模組使用而已,而不是存取它所有的內部程式碼。因為模組相當於一個容器,如果我們只公開模組的話,本身並不能做多少事情。我們需要再進一步選擇公開模組內一些項目才行。 +到底發生了什麼事?在 `mod hosting` 之前加上 `pub` 關鍵字確實公開了模組。有了這項修改後,我們的確可以在取得 `front_of_house` 後,繼續進入 `hosting`。但是 `hosting` 的所有**內容**仍然是私有的。模組中的 `pub` 關鍵字只會讓該模組公開讓上層模組使用而已,而不是存取它所有的內部程式碼。因為模組相當於一個容器,如果我們只公開模組的話,本身並不能做多少事情。我們需要再進一步選擇公開模組內一些項目才行。 範例 7-6 的錯誤訊息表示 `add_to_waitlist` 函式是私有的。隱私權規則如同模組一樣適用於結構體、列舉、函式與方法。 diff --git a/src/ch10-00-generics.md b/src/ch10-00-generics.md index b546fc8c..df044db5 100644 --- a/src/ch10-00-generics.md +++ b/src/ch10-00-generics.md @@ -58,6 +58,6 @@ 2. 將重複的程式碼提取置函式本體內,並指定函式簽名輸入與回傳數值。 3. 更新重複使用程式碼的實例,改呼叫我們定義的函式。 -接著我們將以相同的步驟來使用泛型來減少重複的程式碼。就像函式本體可以抽象出 `list` 而不用特定數值,泛型允許程式碼執行抽象型別。 +接著我們將以相同的步驟使用泛型來減少重複的程式碼。就像函式本體可以抽象出 `list` 而不用特定數值,泛型允許程式碼執行抽象型別。 舉例來說,假設我們有兩個函式:一個會找出 `i32` 型別切片中的最大值而另一個會找出 `char` 型別切片的最大值。我們要如何刪除重複的部分呢?讓我們拭目以待! diff --git a/src/ch10-01-syntax.md b/src/ch10-01-syntax.md index 5b9835cf..7a1ca5d0 100644 --- a/src/ch10-01-syntax.md +++ b/src/ch10-01-syntax.md @@ -1,6 +1,6 @@ ## 泛型資料型別 -我們使用泛型(generics)來建立項目的定義,像是函式簽名或結構體,讓我們在之後可以使用在不同的實際資料型別。讓我們先看看如何使用泛型定義函式、列舉與方法。然後我們會在來看泛型對程式碼的效能影響如何。 +我們使用泛型(generics)來建立項目的定義,像是函式簽名或結構體,讓我們之後可以使用在不同的實際資料型別。讓我們先看看如何使用泛型定義函式、列舉與方法。然後我們會再來看泛型對程式碼的效能影響如何。 ### 在函式中定義 diff --git a/src/ch10-02-traits.md b/src/ch10-02-traits.md index 0184ff1c..4d377d31 100644 --- a/src/ch10-02-traits.md +++ b/src/ch10-02-traits.md @@ -10,7 +10,7 @@ 舉例來說,如果我們有數個結構體各自擁有不同種類與不同數量的文字:結構體 `NewsArticle` 儲存特定地點的新聞故事,然後 `Tweet` 則有最多 280 字元的內容,且有個欄位來判斷是全新的推文、轉推或其他推文的回覆。 -我們想要建立ㄧ個多媒體聚集器函式庫 crate 叫 `aggregator` 來顯示可能存在 `NewsArticle` 或 `Tweet` 實例的資料總結。要達成此目的的話,我們需要每個型別的總結,且我們會呼叫該實例的 `summarize` 方法來索取總結。範例 10-12 顯示了表達此行為的 `Summary` 特徵定義。 +我們想要建立一個多媒體聚集器函式庫 crate 叫 `aggregator` 來顯示可能存在 `NewsArticle` 或 `Tweet` 實例的資料總結。要達成此目的的話,我們需要每個型別的總結,且我們會呼叫該實例的 `summarize` 方法來索取總結。範例 10-12 顯示了表達此行為的 `Summary` 特徵定義。 檔案名稱:src/lib.rs diff --git a/src/ch11-03-test-organization.md b/src/ch11-03-test-organization.md index aa7fd9a8..6bfc028a 100644 --- a/src/ch11-03-test-organization.md +++ b/src/ch11-03-test-organization.md @@ -139,7 +139,7 @@ adder 如果我們的專案只包含 *src/main.rs* 檔案的執行檔 crate 而沒有 *src/lib.rs* 檔案的話,我們無法在 *tests* 目錄下建立整合測試,也無法將 *src/main.rs* 檔案中定義的函式透過 `use` 陳述式引入作用域。只有函式庫 crate 能公開函式給其他 crate 使用,執行檔 crate 只用於獨自執行。 -這也是為何 Rust 專案為執行檔提供直白的 *src/main.rs* 檔案並允許呼叫 *src/lib.rs* 檔案中的邏輯程式碼。使用這樣子的架構的話,整合測試**可以**透過 `use` 來測試函式庫 crate,並讓重點功能可以公開使用。如果重點功能可以運作的話,那 *src/main.rs* 檔案中剩下的程式碼部分也能夠如期執行,而這一小部分就不必特定做測試。 +這也是為何 Rust 專案為執行檔提供直白的 *src/main.rs* 檔案並允許呼叫 *src/lib.rs* 檔案中的邏輯程式碼。使用這樣子的架構的話,整合測試**可以**透過 `use` 來測試函式庫 crate,並讓重點功能可以公開使用。如果重點功能可以運作的話,那 *src/main.rs* 檔案中剩下的程式碼部分也能夠如期執行,而這一小部分就不必特地做測試。 ## 總結 @@ -150,4 +150,4 @@ Rust 的測試功能提供了判定程式碼怎樣才算正常運作的方法, [paths]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html [separating-modules-into-files]: ch07-05-separating-modules-into-different-files.html -[alt-paths]: ch07-05-separating-modules-into-different-files.html#其他種的檔案路徑 \ No newline at end of file +[alt-paths]: ch07-05-separating-modules-into-different-files.html#其他種的檔案路徑 diff --git a/src/ch13-01-closures.md b/src/ch13-01-closures.md index 9bb54a15..667549e4 100644 --- a/src/ch13-01-closures.md +++ b/src/ch13-01-closures.md @@ -131,7 +131,7 @@ let add_one_v4 = |x| x + 1 ; ### `Fn` 特徵以及將獲取的數值移出閉包 -一旦閉包從其定義的周圍環境獲取了數值的參考或所有權(也就是說被**移入**閉包中),閉包本體的程式碼會定義閉包在之後執行結束後要對參考或數值做什麼事情(也就是說被**移出**閉包)。閉包本體可以做以下的事情:將獲取的數值移出閉包、改變獲取的數值、不改變且不移動數值,或是一開始就不從環境獲取任何值。 +一旦閉包從其定義的周圍環境獲取了數值的參考或所有權(也就是說被**移入**閉包中),閉包本體的程式碼會定義閉包在執行結束後要對參考或數值做什麼事情(也就是說被**移出**閉包)。閉包本體可以做以下的事情:將獲取的數值移出閉包、改變獲取的數值、不改變且不移動數值,或是一開始就不從環境獲取任何值。 閉包從周圍環境獲取並處理數值的方式會影響閉包會實作哪種特徵,而這些特徵能讓函式與結構體決定它們想使用哪種閉包。閉包會依照閉包本體處理數值的方式,自動實作一種或多種 `Fn` 特徵: @@ -209,4 +209,4 @@ impl Option { 當我們要在函式或型別中定義與使用閉包時,`Fn` 特徵是很重要的。在下個段落中,我們將討論疊代器。疊代器有許多方法都需要閉包引數,所以隨著我們繼續下去別忘了複習閉包的用法! -[unwrap-or-else]: ../std/option/enum.Option.html#method.unwrap_or_else \ No newline at end of file +[unwrap-or-else]: ../std/option/enum.Option.html#method.unwrap_or_else diff --git a/src/ch15-01-box.md b/src/ch15-01-box.md index 86bb97d0..2c881bf2 100644 --- a/src/ch15-01-box.md +++ b/src/ch15-01-box.md @@ -80,7 +80,7 @@ Box 沒有額外的效能開銷,就只是將它們的資料儲存在堆積上 範例 15-4:嘗試定義遞迴列舉所得到的錯誤 -錯誤顯示此型別的「大小為無限」,原因是因為我們定義的 `List` 有個變體是遞迴:它直接存有另一個相同類型的數值。所以 Rust 無法判別出它需要多少空間才能儲存一個 `List` 的數值。讓我進一步研究為何我們會得到這樣的錯誤,首先來看 Rust 如何決定要配置多少空間來儲存非遞迴型別。 +錯誤顯示此型別的「大小為無限」,原因是因為我們定義的 `List` 有個變體是遞迴:它直接存有另一個相同類型的數值。所以 Rust 無法判別出它需要多少空間才能儲存一個 `List` 的數值。讓我們進一步研究為何會得到這樣的錯誤,首先來看 Rust 如何決定要配置多少空間來儲存非遞迴型別。 #### 計算非遞迴型別的大小 @@ -92,7 +92,7 @@ Box 沒有額外的效能開銷,就只是將它們的資料儲存在堆積上 要決定一個 `Message` 數值需要配置多少空間,Rust 會遍歷每個變體來看哪個變體需要最大的空間。Rust 會看到 `Message::Quit` 不佔任何空間、`Message::Move` 需要能夠儲存兩個 `i32` 的空間,以此類推。因為只有一個變體會被使用,一個 `Message` 數值所需的最大空間就是其最大變體的大小。 -將此對應到當 Rust 嘗試檢查像是範例 15-2 的 `List` 列舉來決定遞迴型別需要多少空間時,究竟會發生什麼事。編譯器先從查看 `Cons` 的變體開始,其存有一個 `i32` 型別與一個 `List` 型別。因此 `Cons` 需要的空間大小為 `i32` 的大小加上 `List` 的大小。為了要瞭解 `List` 型別需要的多少記憶體,編譯器在進一步看它的變體,也是從 `Cons` 變體開始。`Cons` 變體存有一個型別 `i32` 與一個型別 `List`,而這樣的過程就無限處理下去,如圖示 15-1 所示。 +將此對應到當 Rust 嘗試檢查像是範例 15-2 的 `List` 列舉來決定遞迴型別需要多少空間時,究竟會發生什麼事。編譯器先從查看 `Cons` 的變體開始,其存有一個 `i32` 型別與一個 `List` 型別。因此 `Cons` 需要的空間大小為 `i32` 的大小加上 `List` 的大小。為了要瞭解 `List` 型別需要的多少記憶體,編譯器再進一步看它的變體,也是從 `Cons` 變體開始。`Cons` 變體存有一個型別 `i32` 與一個型別 `List`,而這樣的過程就無限處理下去,如圖示 15-1 所示。 An infinite Cons list diff --git a/src/ch15-04-rc.md b/src/ch15-04-rc.md index 9dd43ea8..9e0e2b79 100644 --- a/src/ch15-04-rc.md +++ b/src/ch15-04-rc.md @@ -40,7 +40,7 @@ 我們可以嘗試改用參考來變更 `Cons` 的定義,但是這樣我們就必須指定生命週期參數。透過指定生命週期參數,我們會指定列表中的每個元素會至少活得跟整個列表一樣久。範例 15-17 的元素和列表雖然可以這樣,但不是所有的場合都是如此。 -我們最後可以改用 `Rc` 來變更 `List` 的定義,如範例 15-18 所示。每個 `Cons` 變體都會存有一個數值以及一個由 `Rc` 指向的 `List`。當我們建立 `b` 時,不會取走 `a` 的所有權,我們會克隆(clone) `a` 存有的 `Rc`,因而增加參考的數量從一增加到二,並讓 `a` 與 `b` 共享 `Rc` 資料的所有權。我們也在在建立 `c` 時克隆 `a`,增加參考的數量從二增加到三。每次我們呼叫 `Rc::clone` 時,對 `Rc` 資料的參考計數就會成增加,然後資料不會被清除直到沒有任何參考為止。 +我們最後可以改用 `Rc` 來變更 `List` 的定義,如範例 15-18 所示。每個 `Cons` 變體都會存有一個數值以及一個由 `Rc` 指向的 `List`。當我們建立 `b` 時,不會取走 `a` 的所有權,我們會克隆(clone) `a` 存有的 `Rc`,因而增加參考的數量從一增加到二,並讓 `a` 與 `b` 共享 `Rc` 資料的所有權。我們也在建立 `c` 時克隆 `a`,增加參考的數量從二增加到三。每次我們呼叫 `Rc::clone` 時,對 `Rc` 資料的參考計數就會成增加,然後資料不會被清除直到沒有任何參考為止。 檔案名稱:src/main.rs diff --git a/src/ch15-05-interior-mutability.md b/src/ch15-05-interior-mutability.md index c631fa9d..f36b36c2 100644 --- a/src/ch15-05-interior-mutability.md +++ b/src/ch15-05-interior-mutability.md @@ -29,7 +29,7 @@ * `Box` 能有不可變或可變的借用並在編譯時檢查;`Rc` 則只能有不可變借用並在編譯時檢查:`RefCell` 能有不可變或可變借用但是在執行時檢查。 * 由於 `RefCell` 允許在執行時檢查可變參考,你可以改變 `RefCell` 內部的數值,就算 `RefCell` 是不可變的。 -改變不可變數值內部的值就**內部可變性**模式。讓我們看看內部可變性何時會有用,且觀察為何是可行的。 +改變不可變數值內部的值稱為**內部可變性**模式。讓我們看看內部可變性何時會有用,且觀察為何是可行的。 ### 內部可變性:不可變數值的可變借用 diff --git a/src/ch17-03-oo-design-patterns.md b/src/ch17-03-oo-design-patterns.md index 7c70f78e..bed4b51c 100644 --- a/src/ch17-03-oo-design-patterns.md +++ b/src/ch17-03-oo-design-patterns.md @@ -206,7 +206,7 @@ 我們仍然有 `Post::new` 函式,但是它沒有回傳 `Post` 實例,而是回傳了 `DraftPost` 的實例。因為 `content` 是私有的,而且沒有任何函式回傳 `Post`,所以目前沒有任何辦法能建立 `Post` 的實例。 -`DraftPost` 結構體有個 `add_text` 方法,所以我們可以像之前一樣為 `content` 新增文字,但注意到 `DraftPost` 沒有定義 `content` 方法!所以現在程式確保所有文章都已草稿為起始,而且文章草稿不會提供顯示其內容的方法。任何想嘗試繞過此約束的方式都會產生編譯錯誤。 +`DraftPost` 結構體有個 `add_text` 方法,所以我們可以像之前一樣為 `content` 新增文字,但注意到 `DraftPost` 沒有定義 `content` 方法!所以現在程式確保所有文章都以草稿為起始,而且文章草稿不會提供顯示其內容的方法。任何想嘗試繞過此約束的方式都會產生編譯錯誤。 #### 透過不同型別的轉移來實作狀態轉換 diff --git a/src/ch19-05-macros.md b/src/ch19-05-macros.md index 7439aefe..43f7394c 100644 --- a/src/ch19-05-macros.md +++ b/src/ch19-05-macros.md @@ -78,7 +78,7 @@ let v: Vec = vec![1, 2, 3]; 第二種巨集形式是**程序式巨集**,其行為更像是函式(也是一種程序)。程序式巨集接受一些程式碼作為輸入,操作這些程式碼,然後輸出一些程式碼。和宣告式巨集去匹配模式和取代程式碼的方式不同。三種程序式巨集(自訂 derive,類屬性、類函式)都有著相近的工作方式。 -當建立一個程序式巨集時,該巨集必須放置在自己特殊的一種 crate 中。會這種是因為一些複雜的技術問題,我們希望在未來消弭這個情況。範例 19-29 我們展示了如何定義程序式巨集,其中 `some_attribute` 是一個用來代表特定巨集的佔位符。 +當建立一個程序式巨集時,該巨集必須放置在自己特殊的一種 crate 中。會這樣是因為一些複雜的技術問題,我們希望在未來消弭這個情況。範例 19-29 我們展示了如何定義程序式巨集,其中 `some_attribute` 是一個用來代表特定巨集的佔位符。 檔案名稱:src/lib.rs @@ -162,7 +162,7 @@ $ cargo new hello_macro_derive --lib 我們導入了三個新 crate:`proc_macro`,[`syn`] 和 [`quote`]。`proc_macro` 包含在 Rust 裡面,所以我們不需要將之加入 *Cargo.toml*。`proc_macro` crate 就是編譯器的 API,提供從我們的程式碼讀取和操作 Rust 程式碼。 -`syn` crate 負責從字串解析 Rust 程式碼,轉成我們可以操作的資料結構。而 `qoute` crate 則將 `syn` 的資料結構轉回 Rust 程式碼。撰寫完整的 Rust 程式碼解析器並不是容易的工作,而這些 crate 讓解析任何 Rust 程式碼更為簡便。 +`syn` crate 負責從字串解析 Rust 程式碼,轉成我們可以操作的資料結構。而 `quote` crate 則將 `syn` 的資料結構轉回 Rust 程式碼。撰寫完整的 Rust 程式碼解析器並不是容易的工作,而這些 crate 讓解析任何 Rust 程式碼更為簡便。 當使用者在一個型別上指定 `#[derive(HelloMacro)]`,`hello_macro_derive` 函式就會被呼叫,這是由於我們使用 `proc_macro_derive` 和指定的 `HelloMacro` 名稱來標註 `hello_macro_derive` 函式,而其中的 `HelloMacro` 是我們的特徵名稱。以上就是大多數程序式巨集遵守的慣例。 diff --git a/src/ch20-01-single-threaded.md b/src/ch20-01-single-threaded.md index f4d07d3f..4df9a51f 100644 --- a/src/ch20-01-single-threaded.md +++ b/src/ch20-01-single-threaded.md @@ -112,7 +112,7 @@ headers CRLF message-body ``` -第一行是**請求行(request line)**並持有客戶端想請求什麼的資訊。請求行的第一個部分代表著想使用的**方法(method)**,像是 `GET` 或 `POST`,這描述了客戶端如何產生此請求。在此例中,我們的客戶端使用的是 `GET` 請求 +第一行是**請求行(request line)**並持有客戶端想請求什麼的資訊。請求行的第一個部分代表著想使用的**方法(method)**,像是 `GET` 或 `POST`,這描述了客戶端如何產生此請求。在此例中,我們的客戶端使用的是 `GET` 請求。 請求行的下一個部分是 `/`,這代表客戶端請求的**統一資源標誌符(Uniform Resource Identifier,URI)**,URI 絕大多數(但不是絕對)就等於**統一資源定位符(Uniform Resource Locator,URL)**。URI 與 URL 的差別對於本章節的學習目的來說並不重要,但是 HTTP 規格使用的術語是 URI,所以我們這裡將 URL 替換為 URI。 diff --git a/src/ch20-02-multithreaded.md b/src/ch20-02-multithreaded.md index 00b8f1a8..d2c71adc 100644 --- a/src/ch20-02-multithreaded.md +++ b/src/ch20-02-multithreaded.md @@ -194,7 +194,7 @@ pub fn spawn(f: F) -> JoinHandle 我們將 `std::thread` 引入函式庫 crate 中的作用域,因為我們使用 `thread::JoinHandle` 作為 `ThreadPool` 中向量的項目型別。 -一旦有收到有效大小,`ThreadPool` 就會建立一個可以儲存 `size` 個項目的新向量。`with_capacity` 函式會與 `Vec::new` 做同樣的事,但是有一個關鍵差別:它會預先配置空間給向量。由於我們知道要儲存 `size` 個元素至向量中,這樣的配置方式會比 `Vec::new` 還要些微有效一點,因為後者只會在元素插入時才重新配置自身大小。 +一旦有收到有效大小,`ThreadPool` 就會建立一個可以儲存 `size` 個項目的新向量。`with_capacity` 函式會與 `Vec::new` 做同樣的事,但是有一個關鍵差別:它會預先配置空間給向量。由於我們知道要儲存 `size` 個元素至向量中,這樣的配置方式會比 `Vec::new` 還要略為有效一點,因為後者只會在元素插入時才重新配置自身大小。 當你再次執行 `cargo check`,這次就能成功編譯。 @@ -323,7 +323,7 @@ pub fn spawn(f: F) -> JoinHandle 如果我們得到互斥鎖的話,我們呼叫 `recv` 來從通道中取得 `Job`。最後的 `unwrap` 也繞過了任何錯誤,這在持有發送者的執行緒被關閉時就可能發生;就和如果接收端關閉時 `send` 方法就會回傳 `Err` 的情況類似。 -`recv` 的呼叫會阻擋執行緒,所以如果沒有任何任務的話,當前執行緒對等待直到下一個任務出現為止。`Mutex` 確保同時間只會有一個 `Worker` 執行緒嘗試取得任務。 +`recv` 的呼叫會阻擋執行緒,所以如果沒有任何任務的話,當前執行緒將等待直到下一個任務出現為止。`Mutex` 確保同時間只會有一個 `Worker` 執行緒嘗試取得任務。 我們的執行緒池終於可以運作了!賞它個 `cargo run` 然後下達一些請求吧: