Rust 学习 02

archive time: 2021-06-10

今天我们来看看第三章,Common Programming Concepts

从这一章的标题,Common Programming Concepts,我们就可以清晰地看出这一章讲的是Rust这门编程语言的基础内容,即 变量函数 等等概念

我们这篇博客讲的是Rust中的变量

变量与可变性

在编程语言中,变量,通常意味着一块有命名的,可以存储一定数据的空间,并且在大多数编程语言中,即使这个空间的大小不可以改变,其中存储的内容也是可以改变的,而不能改变的那部分,我们称其为常量

而在Rust里,这个就有点区别了,在Rust中,“变量“默认是不可变的 (immutable),一旦变量与一个值绑定后,你就不能改变这个变量的值了

我们可以用一小段代码来验证一下

fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

通过rustc编译,我们就会得到这样一个报错

[kands@ksc ~/Downloads 17:04] [$] [ yes ]
In[6]:= rustc main.rs
Out[6]:=
error[E0384]: cannot assign twice to immutable variable `x`
 --> main.rs:4:5
  |
2 |     let x = 5;
  |         -
  |         |
  |         first assignment to `x`
  |         help: make this binding mutable: `mut x`
3 |     println!("The value of x is: {}", x);
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0384`.

前文就有提到,Rust的编译器是极为智能的,它清晰地指出了我们的错误,cannot assign twice to immutable variable

Rust中,变量默认是不可变的,既然不可变,就不能够二次赋值 (assign),所以它在这里提醒我们不能给不可变量二次赋值,即重复绑定

如果要改变x的值,可以用之前的办法,即将x改成可变的,在声明变量时,我们在前面加一个mut表示可变变量,这样,这个变量就可以重复赋值了

[kands@ksc ~/Downloads 17:12] [$] [ yes ]
In[9]:= cat main.rs
Out[9]:=
fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}
[kands@ksc ~/Downloads 17:12] [$] [ yes ]
In[10]:= rustc main.rs
Out[10]:=
[kands@ksc ~/Downloads 17:12] [$] [ yes ]
In[11]:= ./main
Out[11]:=
The value of x is: 5
The value of x is: 6

这样,我们的代码就正确执行了

为什么在Rust中要区分可变变量和不可变变量呢?

因为这是可能出现 bug 的地方,Rust出于安全考虑,设计成了可变和不可变,就是为了防止一些变量本来存储了一个值,不能够改变,但在无意之中被其他程序给改变的情况,因为这种错误是极难被发现的

如果你想让这个变量改变,那就需要显式的声明这个变量是可变的,否则就是不可变的,这样就不用担心某个变量的值在不经意间被其他代码给改变的情况了

变量和常量的区别

之前提到了,在Rust中,变量默认是不可变的,而常量也是不可变的,那么这样的变量和常量又有什么区别呢?

首先,你不能在常量前加mut使其变得可变,常量一直是不可变的,而变量仅是默认不可变,但还是可以改变的

要声明一个常量,可以使用const关键字,同时,是什么类型的量也需要说明,即 const X: u16 = 10; 这种形式

还有一个关键点就是常量的值一定是一个不变的表达式,即一个确定的值,而不是像函数的返回值那样,只有在运行时才能得到其返回值

常量在整个程序的运行期间,在其定义的作用域间,都是有效的

Shadowing

这个概念在其他语言里几乎见不到,在Rust中,你可以声明一个重复的变量,同时,新声明的变量会掩盖掉之前那个变量的值

对于这样一段代码,在其他语言里,妥妥的是错误的,重复声明变量,而在Rust中,由于Shadowing机制,这样做是可以的

fn main() {
    let x = 5;
    let x = x + 1;
    let x = x * x;
    println!("The value of x is: {}", x);
}

我们编译运行一下看看结果

[kands@ksc ~/Downloads 17:39] [$] [ yes ]
In[15]:= rustc main.rs
Out[15]:=
[kands@ksc ~/Downloads 17:39] [$] [ yes ]
In[16]:= ./main
Out[16]:=
The value of x is: 36

结果如我们预期一样,

Shadowing与我们之前将变量设为mut来改变变量的值不一样,我们在let的时候就是创建了一个新的变量,同时,我们可以改变这个变量的值甚至是类型

let spaces = "    ";
let spaces = spaces.len()

第二个spaces由字符串变成了整形,如果我们用mut来做,就会得到一个报错

error[E0308]: mismatched types
 --> main.rs:3:14
  |
3 |     spaces = spaces.len();
  |              ^^^^^^^^^^^^ expected `&str`, found `usize`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

这就是我们今天要讲的内容,Rust中的变量,希望能够帮你理清楚Rust变量的规则