你將學習的一個要點是_變量綁定_。它們看起來像這樣:
~~~
fn main() {
let x = 5;
}
~~~
在每個例子中都寫上`fn main() {`有點冗長,所以之后我們將省略它。如果你是一路看過來的,確保你寫了`main()`函數,而不是省略不寫。否則,你將得到一個錯誤。
在許多語言中,這叫做_變量_。不過Rsut的變量綁定有自己的玄機。例如`let`表達式的左側是一個“[模式](http://doc.rust-lang.org/nightly/book/patterns.html)”,而不僅僅是一個變量。這意味著我們可以這樣寫:
~~~
let (x, y) = (1, 2);
~~~
在這個表達式被計算后,`x`將會是1,而`y`將會是2.模式非常強大,并且本書中有[關于它的部分](http://doc.rust-lang.org/nightly/book/patterns.html)。我們現在還不需要這些功能,所以接下來你只需記住有這個東西就行了。
Rust是一個靜態類型語言,這意味著我們需要先確定我們需要的類型。那為什么我們第一例子能編譯過呢?嘛,Rust有一個叫做_類型推斷_的功能。如果它能確認這是什么類型,Rust不需要你非要把它寫出來。
若你愿意,我們也可以加上類型。類型寫在一個冒號(:)后面:
~~~
let x: i32 = 5;
~~~
如果我叫你對著全班同學大聲讀出這一行,你應該大喊“`x`被綁定為`i32類`型,它的值是`5`”。
在這個例子中我們選擇`x`代表一個32位的有符號整數。Rust有許多不同的原生整數類型。以`i`開頭的代表有符號整數而`u`開頭的代表無符號整數。可能的整數大小是8,16,32和64位。
在之后的例子中,我們可能會在注釋中注明變量類型。例子看起來像這樣:
~~~
fn main() {
let x = 5; // x: i32
}
~~~
注意注釋和`let`表達式有類似的語法。理想的Rust代碼中不應包含這類注釋。不過我們偶爾會這么做來幫助你理解Rust推斷的是什么類型。
綁定默認是_不可變的_(_immutable_)。下面的代碼將不能編譯:
~~~
let x = 5;
x = 10;
~~~
它會給你如下錯誤:
~~~
error: re-assignment of immutable variable `x`
x = 10;
^~~~~~~
~~~
如果你想一個綁定是可變的,使用`mut`:
~~~
let mut x = 5; // mut x: i32
x = 10;
~~~
不止一個理由使得綁定默認不可變的,不過我們可以理解它通過一個Rust的主要目標:安全。如果你沒有使用`mut`,編譯器會捕獲它,讓你知道你改變了一個你可能并不打算讓它改變的值。如果綁定默認是可變的,編譯器將不可能告訴你這些。如果你確實想變量可變,解決辦法也非常簡單:加個`mut`。
盡量避免可變狀態有一些其它好處,不過這不在這個教程的討論范圍內。大體上,你總是可以避免顯式可變量,并且這也是Rust希望你做的。即便如此,有時,可變量是你需要的,所以這并不是被禁止的。
讓我們回到綁定。Rust變量綁定有另一個不同于其它語言的方面:綁定要求在可以使用它之前必須初始化。
讓我們嘗試一下。將你的`src/main.rs`修改為為如下:
~~~
fn main() {
let x: i32;
println!("Hello world!");
}
~~~
你可以用`cargo build`命令去構建它。它依然會輸出“Hello, world!”,不過你會得到一個警告:
~~~
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警告我們從未使用過這個變量綁定,但是因為我們從未用過它,無害不罰。然而,如果你確實想使用`x`,事情就不一樣了。讓我們試一下。修改代碼如下:
~~~
fn main() {
let x: i32;
println!("The value of x is: {}", x);
}
~~~
然后嘗試構建它。你會得到一個錯誤:
~~~
$ 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是不會讓我們使用一個沒有經過初始化的值的。接下來,讓我們討論一下我們添加到`println!`中的內容。
如果你輸出的字符串中包含一對大括號(`{}`,一些人稱之為。。胡須(moustaches)?),Rust將把它解釋為插入值的請求。_字符串插值_(_String interpolation_)是一個計算機科學術語,代表“在字符串中插入值”。我們加上一個逗號,然后是一個`x`,來表示我們想插入`x`的值。逗號用來分隔我們傳遞給函數和宏的參數,如果你想傳遞多個參數的話。
當你只寫了大括號的時候,Rust會嘗試檢查值的類型來顯示一個有意義的值。如果你想指定詳細的語法,這里有[很多選項可供選擇](http://doc.rust-lang.org/std/fmt/)。現在,讓我們保持默認,整數并不難打印。
- 前言
- 1.介紹
- 2.準備
- 2.1.安裝Rust
- 2.2.Hello, world!
- 2.3.Hello, Cargo!
- 3.學習Rust
- 3.1.猜猜看
- 3.2.哲學家就餐問題
- 3.3.其它語言中的Rust
- 4.高效Rust
- 4.1.棧和堆
- 4.2.測試
- 4.3.條件編譯
- 4.4.文檔
- 4.5.迭代器
- 4.6.并發
- 4.7.錯誤處理
- 4.8.外部語言接口
- 4.9.Borrow 和 AsRef
- 4.10.發布途徑
- 5.語法和語義
- 5.1.變量綁定
- 5.2.函數
- 5.3.原生類型
- 5.4.注釋
- 5.5.If語句
- 5.6.for循環
- 5.7.while循環
- 5.8.所有權
- 5.9.引用和借用
- 5.10.生命周期
- 5.11.可變性
- 5.12.結構體
- 5.13.枚舉
- 5.14.匹配
- 5.15.模式
- 5.16.方法語法
- 5.17.Vectors
- 5.18.字符串
- 5.19.泛型
- 5.20.Traits
- 5.21.Drop
- 5.22.if let
- 5.23.trait對象
- 5.24.閉包
- 5.25.通用函數調用語法
- 5.26.包裝箱和模塊
- 5.27.`const`和`static`
- 5.28.屬性
- 5.29.`type`別名
- 5.30.類型轉換
- 5.31.關聯類型
- 5.32.不定長類型
- 5.33.運算符和重載
- 5.34.`Deref`強制多態
- 5.35.宏
- 5.36.裸指針
- 6.Rust開發版
- 6.1.編譯器插件
- 6.2.內聯匯編
- 6.3.不使用標準庫
- 6.4.固有功能
- 6.5.語言項
- 6.6.鏈接參數
- 6.7.基準測試
- 6.8.裝箱語法和模式
- 6.9.切片模式
- 6.10.關聯常量
- 7.詞匯表
- 8.學院派研究
- 勘誤