鍍金池/ 教程/ Java/ 變量綁定
哲學(xué)家就餐問題
鏈接進(jìn)階
名詞中英文對(duì)照
測(cè)試
引用和借用
泛型
方法語法
函數(shù)
不安全代碼
并發(fā)
裝箱語法和模式
注釋
棧和堆
運(yùn)算符與重載
語法索引
文檔
固有功能
所有權(quán)
循環(huán)
通用函數(shù)調(diào)用語法
不定長(zhǎng)類型
<code>const</code> 和 <code>static</code>
迭代器
其他語言中的 Rust
枚舉
詞匯表
If語句
猜猜看
錯(cuò)誤處理
生命周期
編譯器插件
發(fā)布途徑
閉包
trait 對(duì)象
不使用標(biāo)準(zhǔn)庫
關(guān)聯(lián)常量
外部函數(shù)接口(FFI)
類型轉(zhuǎn)換
原生類型
匹配
參考文獻(xiàn)
Rust 編程語言
內(nèi)聯(lián)匯編
條件編譯
選擇你的保證
學(xué)習(xí) Rust
`type`別名
自定義內(nèi)存分配器
屬性
if let
高效 Rust
可變性
語法和語義
模式
基準(zhǔn)測(cè)試
結(jié)構(gòu)體
變量綁定
語言項(xiàng)
切片模式
<code>Deref</code> 強(qiáng)制多態(tài)
關(guān)聯(lián)類型
裸指針
<code>Borrow</code> 和 <code>AsRef</code>
準(zhǔn)備
Rust 開發(fā)版
字符串

變量綁定

variable-bindings.md
commit 6ba952020fbc91bad64be1ea0650bfba52e6aab4

事實(shí)上每一個(gè)非“Hello World” Rust 程序都用了變量綁定。他們將一些值綁定到一個(gè)名字上,這樣可以在之后使用他們。let被用來聲明一個(gè)綁定,像這樣:

fn main() {
    let x = 5;
}

在每個(gè)例子中都寫上fn main() {有點(diǎn)冗長(zhǎng),所以之后我們將省略它。如果你是一路看過來的,確保你寫了main()函數(shù),而不是省略不寫。否則,你將得到一個(gè)錯(cuò)誤。

模式(Patterns)

在許多語言中,這叫做變量。不過 Rust 的變量綁定有一些不同的巧妙之處。例如let表達(dá)式的左側(cè)是一個(gè)“[模式](Patterns 模式.md)”,而不僅僅是一個(gè)變量。這意味著我們可以這樣寫:

let (x, y) = (1, 2);

在這個(gè)表達(dá)式被計(jì)算后,x將會(huì)是1,而y將會(huì)是2.模式非常強(qiáng)大,并且本書中有[關(guān)于它的部分](Patterns 模式.md)。我們現(xiàn)在還不需要這些功能,所以接下來你只需記住有這個(gè)東西就行了。

類型注解(Type annotations)

Rust 是一個(gè)靜態(tài)類型語言,這意味著我們需要先確定我們需要的類型。那為什么我們第一個(gè)例子能編譯過呢?好的,Rust有一個(gè)叫做類型推斷的功能。如果它能確認(rèn)這是什么類型,Rust 不需要你明確地指出來。

若你愿意,我們也可以加上類型。類型寫在一個(gè)冒號(hào)(:)后面:

let x: i32 = 5;

如果我叫你對(duì)著全班同學(xué)大聲讀出這一行,你應(yīng)該大喊“x被綁定為i32類型,它的值是5”。

在這個(gè)例子中我們選擇x代表一個(gè) 32 位的有符號(hào)整數(shù)。Rust 有許多不同的原生整數(shù)類型。以i開頭的代表有符號(hào)整數(shù)而u開頭的代表無符號(hào)整數(shù)??赡艿恼麛?shù)大小是 8,16,32 和 64 位。

在之后的例子中,我們可能會(huì)在注釋中注明變量類型。例子看起來像這樣:

fn main() {
    let x = 5; // x: i32
}

注意注釋和let表達(dá)式有類似的語法。理想的 Rust 代碼中不應(yīng)包含這類注釋。不過我們偶爾會(huì)這么做來幫助你理解 Rust 推斷的是什么類型。

可變性(Mutability)

綁定默認(rèn)是不可變的immutable)。下面的代碼將不能編譯:

let x = 5;
x = 10;

它會(huì)給你如下錯(cuò)誤:

error: re-assignment of immutable variable `x`
     x = 10;
     ^~~~~~~

如果你想一個(gè)綁定是可變的,使用mut

let mut x = 5; // mut x: i32
x = 10;

不止一個(gè)理由使得綁定默認(rèn)不可變的,不過我們可以通過一個(gè) Rust 的主要目標(biāo)來理解它:安全。如果你沒有使用mut,編譯器會(huì)捕獲它,讓你知道你改變了一個(gè)你可能并不打算讓它改變的值。如果綁定默認(rèn)是可變的,編譯器將不可能告訴你這些。如果你確實(shí)想變量可變,解決辦法也非常簡(jiǎn)單:加個(gè)mut。

盡量避免可變狀態(tài)有一些其它好處,不過這不在這個(gè)教程的討論范圍內(nèi)。大體上,你總是可以避免顯式可變量,并且這也是 Rust 希望你做的。即便如此,有時(shí),可變量是你需要的,所以這并不是被禁止的。

初始化綁定(Initializing bindings)

Rust 變量綁定有另一個(gè)不同于其它語言的方面:綁定要求在可以使用它之前必須初始化。

讓我們嘗試一下。將你的src/main.rs修改為為如下:

fn main() {
    let x: i32;

    println!("Hello world!");
}

你可以用cargo build命令去構(gòu)建它。它依然會(huì)輸出“Hello, world!”,不過你會(huì)得到一個(gè)警告:

   Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default
src/main.rs:2     let x: i32;
                      ^

Rust 警告我們從未使用過這個(gè)變量綁定,但是因?yàn)槲覀儚奈从眠^它,無害不罰。然而,如果你確實(shí)想使用x,事情就不一樣了。讓我們?cè)囈幌?。修改代碼如下:

fn main() {
    let x: i32;

    println!("The value of x is: {}", x);
}

然后嘗試構(gòu)建它。你會(huì)得到一個(gè)錯(cuò)誤:

$ cargo build
   Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
src/main.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
src/main.rs:4     println!("The value of x is: {}", x);
                                                    ^
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
src/main.rs:4:5: 4:42 note: expansion site
error: aborting due to previous error
Could not compile `hello_world`.

Rust 是不會(huì)讓我們使用一個(gè)沒有經(jīng)過初始化的值的。接下來,讓我們討論一下我們添加到println!中的內(nèi)容。

如果你輸出的字符串中包含一對(duì)大括號(hào)({},一些人稱之為胡須。。(譯注:moustaches,八字胡)),Rust將把它解釋為插入值的請(qǐng)求。字符串插值String interpolation)是一個(gè)計(jì)算機(jī)科學(xué)術(shù)語,代表“在字符串中插入值”。我們加上一個(gè)逗號(hào),然后是一個(gè)x,來表示我們想插入x的值。逗號(hào)用來分隔我們傳遞給函數(shù)和宏的參數(shù),如果你想傳遞多個(gè)參數(shù)的話。

當(dāng)你只寫了大括號(hào)的時(shí)候,Rust 會(huì)嘗試檢查值的類型來顯示一個(gè)有意義的值。如果你想指定詳細(xì)的語法,有很多選項(xiàng)可供選擇?,F(xiàn)在,讓我們保持默認(rèn)格式,整數(shù)并不難打印。

作用域和隱藏(Scope and shadowing)

讓我們回到綁定。變量綁定有一個(gè)作用域 - 他們被限制只能在他們被定義的塊中存在。一個(gè)塊是一個(gè)被{}包圍的語句集合。函數(shù)定義也是塊!在下面的例子中我們定義了兩個(gè)變量綁定,xy,他們位于不同的作用域中。x可以在fn main() {}塊中被訪問,而y只能在內(nèi)部塊內(nèi)訪問:

fn main() {
    let x: i32 = 17;
    {
        let y: i32 = 3;
        println!("The value of x is {} and value of y is {}", x, y);
    }
    println!("The value of x is {} and value of y is {}", x, y); // This won't work
}

第一個(gè)println!將會(huì)打印“The value of x is 17 and the value of y is 3”,不過這個(gè)并不能編譯成功,因?yàn)榈诙€(gè)println!并不能訪問y的值,因?yàn)樗巡辉谧饔糜蛑小O喾次覀兊玫饺缦洛e(cuò)誤:

$ cargo build
   Compiling hello v0.1.0 (file:///home/you/projects/hello_world)
main.rs:7:62: 7:63 error: unresolved name `y`. Did you mean `x`? [E0425]
main.rs:7     println!("The value of x is {} and value of y is {}", x, y); // This won't work
                                                                       ^
note: in expansion of format_args!
<std macros>:2:25: 2:56 note: expansion site
<std macros>:1:1: 2:62 note: in expansion of print!
<std macros>:3:1: 3:54 note: expansion site
<std macros>:1:1: 3:58 note: in expansion of println!
main.rs:7:5: 7:65 note: expansion site
main.rs:7:62: 7:63 help: run `rustc --explain E0425` to see a detailed explanation
error: aborting due to previous error
Could not compile `hello`.

To learn more, run the command again with --verbose.

另外,變量可以被隱藏。這意味著一個(gè)后聲明的并位于同一作用域的相同名字的變量綁定將會(huì)覆蓋前一個(gè)變量綁定:

let x: i32 = 8;
{
    println!("{}", x); // Prints "8"
    let x = 12;
    println!("{}", x); // Prints "12"
}
println!("{}", x); // Prints "8"
let x =  42;
println!("{}", x); // Prints "42"

隱藏和可變綁定可能作為同一枚硬幣的兩面出現(xiàn),不過他們是兩個(gè)并不總是能交替使用的不同的概念。作為其中之一,隱藏允許我們重綁定一個(gè)值為不同的類型。它也可以改變一個(gè)綁定的可變性:

let mut x: i32 = 1;
x = 7;
let x = x; // x is now immutable and is bound to 7

let y = 4;
let y = "I can also be bound to text!"; // y is now of a different type
上一篇:切片模式下一篇:If語句