Rust 2.4 变量绑定
10 Jan 2015 by LelouchHe
我们学习的第一个是”变量绑定”(variable binding).像这样:
fn main() {
let x = 5;
}
一直写fn main() { ... }
是比较麻烦的,所以后面我们就忽略这个了.要是你的话,注意要把这个加进去.要不然,是编译不过的.
在很多语言中,这都叫做”变量”(variable).但Rust的变量绑定有些trick.后面我们会学到,Rust有一个叫做”模式匹配”(pattern matching)的强大功能,表达式let
左边就是一个模式(full pattern),而不仅仅是变量名.这意味着我们可以这样:
let (x, y) = (1, 2);
表达式求值后,x等于1,y等于2.模式是非常强大的,但现在我们只介绍这一些.所以我们先记着这些,后面再说.
Rust是静态类型语言,我们必须确定提前确定类型才行.那为什么第一个例子可以编译的?是因为Rust有类型推导(type inference).如果Rust能自己推导出具体的类型,就不需要我们把类型标出了.
如果我们愿意,我们可以手动添加类型.类型放在冒号(“:”)后即可:
let x: i32 = 5;
如果我让你把这句话都出来,应该读作”x绑定的类型是i32,值是5”.
后面的例子中,我们会把类型标在注释里(译者: BTW,注释类似于C的注释).像这样:
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;
x = 10;
(译者: 但此时也会给你warning的)
默认绑定不可变的原因有很多,但我们可以从Rust的目标来看:安全.如果你忘记添加mut
,编译器会检查出这个错误,告诉你你可能改变了某些不能改变的东西.如果绑定默认是可变的,编译器就无能为力了.如果你确实要改变的话,就简单的增加mut
即可.
尽可能的避免可变状态的原因很多,但这些都不在本教程范围内.你通常可以避免显式的绑定改变,故不可变绑定在Rust是默认的.但有时改变是必须的,所以改变也是允许的.
我们回到绑定来.Rust的变量绑定有个不同其他语言之处: 变量使用之前,必须进行绑定初始化.如果我们这样:
let x;
我们就会得到error(译者: 这是当前最新版的错误信息,故和原文有些许不同):
error: unable to infer enough type information about '_'; type annotation required
let x;
^
显式指定类型即可编译通过:
let x: i32;
让我们像这样试试:
fn main() {
let x: i32;
println!("Hello, world!");
}
你可以用cargo build
来构建.你会得到一个warning,但还是会编译通过的:
warning: unused variable: `x`
let x: i32;
^
Rust警告我们有未使用的绑定,但由于我们没使用,所以也没关系.如果我们真的用到了x
,就有问题了.像下面这样:
fn main() {
let x: i32;
println!("The variable of x is: {}", x);
}
构建时,就会得到错误:
error: use of possibly uninitialized variable: `x`
Rust不允许我们使用未初始化的值.接下来,我们介绍下给println!
添加的东西
如果你在要输出的字符串中添加了双大括号(“{}”),Rust就会把它当作插值(interpolate)的占位符.字符串插值(string interpolation)在计算机术语中是”中间插入字符串”的意思.我们在后面加一个逗号(“,”),再写上x
,就表示我们想把x
插值.逗号是用来分隔传递给函数和宏的参数的.
当你只使用双大括号时,Rust会根据后面对应参数的类型进行有意义的展示.如果你要手动的操作输出格式,有一系列特定的选项.现在,我们只使用默认的操作:毕竟整数还是很容易输出的嘛.