Skip to content

Commit

Permalink
Merge pull request #200 from 2020leon/typo
Browse files Browse the repository at this point in the history
fix: fix typos
  • Loading branch information
wusyong authored Feb 15, 2024
2 parents 165a8cd + 3f7560e commit 0d4a61b
Show file tree
Hide file tree
Showing 8 changed files with 10 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
let gen = quote! {
impl HelloMacro for #name {
fn hello_macro() {
println!("你好,巨集我叫做{}!", stringify!(#name));
println!("你好,巨集我叫做{}!", stringify!(#name));
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
let gen = quote! {
impl HelloMacro for #name {
fn hello_macro() {
println!("你好,巨集我叫做{}!", stringify!(#name));
println!("你好,巨集我叫做{}!", stringify!(#name));
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/ch10-02-traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

### 為型別實作特徵

現在我們已經用 `Summary` 特徵定義了所需的方法簽名。我們可以在我們多媒體聚集器的型別中實作它。範例 10-13 顯示了 `NewsArticle` 結構體實作 `Summary` 特徵的方式,其使用頭條、作者、位置來建立 `summerize` 的回傳值。至於結構體 `Tweet`,我們使用使用者名稱加上整個推文的文字來定義 `summarize`,因為推文的內容長度已經被限制在 280 個字元以內了。
現在我們已經用 `Summary` 特徵定義了所需的方法簽名。我們可以在我們多媒體聚集器的型別中實作它。範例 10-13 顯示了 `NewsArticle` 結構體實作 `Summary` 特徵的方式,其使用頭條、作者、位置來建立 `summarize` 的回傳值。至於結構體 `Tweet`,我們使用使用者名稱加上整個推文的文字來定義 `summarize`,因為推文的內容長度已經被限制在 280 個字元以內了。

<span class="filename">檔案名稱:src/lib.rs</span>

Expand Down
2 changes: 1 addition & 1 deletion src/ch15-06-reference-cycles.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## 參考循環會導致記憶體泄漏

意外情況下,執行程式時可能會產生永遠不會被清除的記憶體(通稱為**記憶體泄漏/memory leak**)。Rust 的記憶體安全性雖然可以保證令這種情況難以發生,但並非絕不可能。雖然 Rust 在編譯時可以保證做到禁止資料競爭(**data races**),但它無法保證完全避免記憶體泄漏,這是因為對 Rust 來說,記憶體泄漏是屬於安全範疇內的(**memory safe**)。透過使用 `Rc<T>``RefCell<T>` ,我們能觀察到 Rust 允許使用者自行產生記憶體泄漏:因為使用者可以產生兩個參考並互相參照,造成一個循環。這種情況下會導致記憶體泄漏,因為循環中的參考計數永遠不會變成 0,所以數值永遠不會被釋放。
意外情況下,執行程式時可能會產生永遠不會被清除的記憶體(通稱為**記憶體泄漏/memory leak**)。Rust 的記憶體安全性雖然可以保證令這種情況難以發生,但並非絕不可能。雖然 Rust 在編譯時可以保證做到禁止資料競爭(**data races**),但它無法保證完全避免記憶體泄漏,這是因為對 Rust 來說,記憶體泄漏是屬於安全範疇內的(**memory safe**。透過使用 `Rc<T>``RefCell<T>` ,我們能觀察到 Rust 允許使用者自行產生記憶體泄漏:因為使用者可以產生兩個參考並互相參照,造成一個循環。這種情況下會導致記憶體泄漏,因為循環中的參考計數永遠不會變成 0,所以數值永遠不會被釋放。

### 產生參考循環

Expand Down
2 changes: 1 addition & 1 deletion src/ch19-01-unsafe-rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ Rust 的全域變數稱做**靜態**變數。範例 19-9 展示了宣告並使

<span class="caption">範例 19-10:讀取與寫入可變的靜態變數為不安全的操作</span>

與普通變數一樣,我們透過 `mut` 關鍵字指明可變性。任何讀寫 `COURTER` 的程式碼皆必須在 `unsafe` 區塊中。這個程式碼會編譯並打印出我們預期中的 `COUNTER: 3` 是因為他在單執行緒執行,若在多執行緒存取 `COUTER` 則可能導致資料競爭。
與普通變數一樣,我們透過 `mut` 關鍵字指明可變性。任何讀寫 `COURTER` 的程式碼皆必須在 `unsafe` 區塊中。這個程式碼會編譯並打印出我們預期中的 `COUNTER: 3` 是因為他在單執行緒執行,若在多執行緒存取 `COUNTER` 則可能導致資料競爭。

當能從全域存取可變資料時,確保沒有資料競爭就不容易了,這就是為什麼 Rust 將可變的靜態變數視為不安全。若是可能的話,我們推薦使用第十六章討論的並行技術與執行緒安全(thread-safe)的智慧指標(smart pointer),如此一來編譯器就能檢查從不同執行緒存取資料是安全的。

Expand Down
2 changes: 1 addition & 1 deletion src/ch19-02-advanced-traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ Rust 並沒有限制不同特徵之間不能有同名的方法,也沒有阻止

因為 `Wrapper` 是一個元組結構體而 `Vec<T>` 是該元組在索引 0 上的項目,所以該 `Display` 的實作使用 `self.0` 存取內部的 `Vec<T>`。我們就可以在 `Wrapper` 上使用 `Display` 的功能了。

使用這個技術的缺點是 `Wrapper` 是個新型別,並無它封裝的值所擁有的方法。我們不得不在 `Wapper` 上實作所有 `Vec<T>` 的方法,委派這些方法給 `self.0`,讓我們可以將 `Wrapper` 作為 `Vec<T>` 一樣對待。如果我們想要新型別得到所有內部型別擁有的所有方法,一個解法是透過對 `Wrapper` 實作 `Deref` 特徵(在第十五章[「透過 `Deref` 特徵將智慧指標視為一般參考」][智慧指標取值]一節有相應討論)並回傳內部型別。如果我們不想要 `Wrapper` 擁有所有內部型別的方法,例如限制 `Wrapper` 型別之行為,就僅須實作那些我們想要的方法。
使用這個技術的缺點是 `Wrapper` 是個新型別,並無它封裝的值所擁有的方法。我們不得不在 `Wrapper` 上實作所有 `Vec<T>` 的方法,委派這些方法給 `self.0`,讓我們可以將 `Wrapper` 作為 `Vec<T>` 一樣對待。如果我們想要新型別得到所有內部型別擁有的所有方法,一個解法是透過對 `Wrapper` 實作 `Deref` 特徵(在第十五章[「透過 `Deref` 特徵將智慧指標視為一般參考」][智慧指標取值]一節有相應討論)並回傳內部型別。如果我們不想要 `Wrapper` 擁有所有內部型別的方法,例如限制 `Wrapper` 型別之行為,就僅須實作那些我們想要的方法。

現在,你知道如何將新型別模式與特徵相關聯,縱使不涉及特徵,新型別模式仍非常實用。接下來我們將目光轉移到其他與 Rust 型別系統互動的方法吧。

Expand Down
4 changes: 2 additions & 2 deletions src/ch19-03-advanced-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Rust 有一個特殊的型別叫做 `!`,由於它沒有任何值,在型別
{{#rustdoc_include ../listings/ch19-advanced-features/no-listing-08-match-arms-different-types/src/main.rs:here}}
```

這段程式碼中 `guess` 的型別必須是**同時是**整數與字串,並且 Rust 要求 `guess` 只能是一種型別。那 `contiunue` 回傳了什麼?範例 19-26 中,為什麼允許一個分支回傳 `u32` 但同時有另一分支結束在 `continue`
這段程式碼中 `guess` 的型別必須是**同時是**整數與字串,並且 Rust 要求 `guess` 只能是一種型別。那 `continue` 回傳了什麼?範例 19-26 中,為什麼允許一個分支回傳 `u32` 但同時有另一分支結束在 `continue`


如你所猜,`continue` 具有 `!` 值。意即當 Rust 根據兩個分支來推算 `guess` 型別時,會觀察到前者會是 `u32`,而後者是 `!`。因為 `!` 永遠不會有值,Rust 於是決定 `guess` 的型別為 `u32`
Expand All @@ -123,7 +123,7 @@ Rust 有一個特殊的型別叫做 `!`,由於它沒有任何值,在型別

### 動態大小型別與 `Sized` 特徵

Rust 需要了解其型別的特定細節,例如需替特定型別之值配置多少空間。這導致型別系統有令人困惑的小地方:即是**動態大小型別**(dynamically sized type)的概念。有時稱為 *DST***不定大小(unsize)型別**,這些型別賦予我們寫出僅能在執行期(runtime)得知值的大小之程式碼。
Rust 需要了解其型別的特定細節,例如需替特定型別之值配置多少空間。這導致型別系統有令人困惑的小地方:即是**動態大小型別**(dynamically sized type)的概念。有時稱為 *DST***不定大小(unsized)型別**,這些型別賦予我們寫出僅能在執行期(runtime)得知值的大小之程式碼。

讓我們深入研究一個貫穿全書到處使用的動態大小型別 `str` 的細節。你沒看錯,不是 `&str` 而是 `str` 本身就是 DST。在執行期前我們無從得知字串多長,也就表示無法建立一個型別為 `str` 的變數,更不能將 `str` 型別作為引數。試想以下不能執行的程式碼:

Expand Down
4 changes: 2 additions & 2 deletions src/ch19-05-macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ pub fn some_name(input: TokenStream) -> TokenStream {

### 如何撰寫自訂的 `derive` 巨集

我們建立一個 `hello_macro` crate,並定義 `HelloMacro` 特徵與它的 `hello_macro` 關聯函式。我們提供一個程序式巨集,讓 crate 的使用者透過 `#[derive(HelloMacro)]` 標註它們的型別,來獲得預設的 `hello_macro` 函式的實作,而不需要使用者替每個型別手動實作 `HelloMacro` 特徵。這個預設的函式實作會印出 `你好,巨集我叫做型別名稱!`,其中 `型別名稱` 是實作特徵那個型別的名字。換句話說,就是我們會寫出一個 crate,讓其他程式設計師用我們的 crate,以範例 19-30 的方式來寫程式。
我們建立一個 `hello_macro` crate,並定義 `HelloMacro` 特徵與它的 `hello_macro` 關聯函式。我們提供一個程序式巨集,讓 crate 的使用者透過 `#[derive(HelloMacro)]` 標註它們的型別,來獲得預設的 `hello_macro` 函式的實作,而不需要使用者替每個型別手動實作 `HelloMacro` 特徵。這個預設的函式實作會印出 `你好,巨集我叫做型別名稱!`,其中 `型別名稱` 是實作特徵那個型別的名字。換句話說,就是我們會寫出一個 crate,讓其他程式設計師用我們的 crate,以範例 19-30 的方式來寫程式。

<span class="filename">檔案名稱:src/main.rs</span>

Expand Down Expand Up @@ -212,7 +212,7 @@ DeriveInput {

`quote!` 巨集也提供非常炫的模板機制:我們可以輸入 `#name`,而 `quote!` 會以變數 `name` 值取而代之。我們甚至可以做一些類似普通巨集的重複工作。閱讀 [`quote` crate 的文件][quote-docs]以獲得完整的介紹。

我們想要我們的程序式巨集對使用者標註的型別產生 `HelloMacro` 特徵的實作,這個標註的型別名稱可以從 `#name` 取得。這個特徵的實作有一個函式 `hello_macro`,函式本體包含我們想要的功能:印出 `你好,巨集我叫做` 再加上被標註的型別的名稱。
我們想要我們的程序式巨集對使用者標註的型別產生 `HelloMacro` 特徵的實作,這個標註的型別名稱可以從 `#name` 取得。這個特徵的實作有一個函式 `hello_macro`,函式本體包含我們想要的功能:印出 `你好,巨集我叫做` 再加上被標註的型別的名稱。

`stringify!` 巨集是 Rust 內建的,會將一個 Rust 表達式,例如 `1 + 2`,在編譯期轉換成字串字面值(string literal),例如 `"1 + 2"`。這和 `format!``println!` 巨集會對表達式求值並將結果轉為 `String` 不同。因為輸入的 `#name` 可能是一個表達式,但要直接照字面印出來,所以我們選擇使用 `stringify!`。使用 `stringify!` 也可以節省在編譯器因為轉換 `#name` 成為字串字面量所需的空間配置。

Expand Down

0 comments on commit 0d4a61b

Please sign in to comment.