可变(mutable)与不可变(immutable)1Rust(1) 基本语法编程语言闲话编程Contents可变(mutable)与不可变(immutable) ................................................................. 1基本类型 ............................................................................................... 2标量类型复合类型方法 .................................................................................................... 3流程控制 ............................................................................................... 3语句条件赋值循环rust语言的一些惯例 .................................................................................. 5命名方式使用语言编写再容易不过了:fn main() { println!("Hello world!");}然后利用编译器编译即可rustc hell.rs -o hello.out && ./hello.out可变(mutable)与不可变(immutable)程序默认的变量是不可变的,类似这种函数式编程的语言,鼓励用户使用的变量。当然如果你非想要使用可变的对象也是支持的:let i = 32; // immutablelet mut i = 32;编译器会检查是否对不可变对象重新赋值 |4 | let i = 10; | - | | | first assignment to `i` | help: make this binding mutable: `mut i`...7 | i = 99; | ^^^^^^ cannot assign twice to immutable variable那么,对于简单类型直接赋值会有问题,如果是复杂类型,如何呢?比如我们用一个不可变的字符串,然后去调用它的函数改变值,会发生生么情况呢?--> test.rs:5:5 |4 | let s = String::from("hello"); | - help: consider changing this to be mutable: `mut s`5 | s.push_str(" world!!!"); | ^ cannot borrow as mutable 基本类型2结果表明,依然保持对象是不可变的。看了一下这个方法的定义,有些蹊跷:pub fn push_str(&mut self, string: &str) { self.vec.extend_from_slice(string.as_bytes())}具体怎么做到的,我们后面再来研究。基本类型跟大多数编译型语言一样是静态类型的语言,即所有的变量的类型在程序编译的时候就是已知的。在语言中,有着如下的基本类型:标量类型(Scalar types)类型长度并不等同于是默认类型,通常拥有最快的速度取决于机器架构,在位机器上位位,位上位位浮点数使用标准let f = true;let sum:i32 = 100;let heart_eyed_cat = '';复合类型(Compound types)复合类型分为元组()和数组。元组可以用来将不同类型的解构组合到一起:let t: (i32, bool) = (100, false);let (x, y) = t; // 解构元组let x = t.0; // 或者通过序号访问数组的与元组的区别在于数组中包含的都是同一种数据类型的值。let a = [1, 2, 3];let a: [i32; 5] = [1, 2, 3, 4, 5]; // 显示声明一个数组let b = [10; 5]; // 声明初始值为10、长度为5的数组值得注意的是,在中元组和数组都是固定长度的,一旦声明以后就不可以更改。如果非要可变长度的集合,那么可以考虑使用标准库中的vector。并且数组中的元素也是不可以更改的,如果尝试去更改一个不可变的对象编译时会出错:6 | let b = [100; 5]; | - help: consider changing this to be mutable: `mut b` 流程控制37 | b[1] = 1024; | ^^^^^^^^^^^ cannot assign这和一些其他的语言例如中的是有区别的。数组中如果如果声明的长度和和实际值的长度不一样会怎样呢?在编译时就会出错: --> hell.rs:11:23 |11 | let a: [i32; 3] = [1]; | ^^^ expected an array with a fixed size of 3 elements, found one with 1 element另外,程序会在运行时对数组的边界进行检查,如果越界访问数组将抛出错误而结束程序,而不是返回一个错误的内存。方法在中定义一个方法使用fn关键字定义:fn foo(i: i32, j: i32) { let sum = i + j}// 带有返回值的方法fn sum(i: i32, j: i32) -> i32 { i + j}在中方法是第一类值,意味着你可以这样操作:let fn_s = sum;let s = fn_s(i, j);另外,方法中包含在大括号中的语句块,被称作是表达式,可以这样用:let a = { e + 10};println!("{}", a);流程控制if语句的语句和其他语言基本类似,稍微有一点区别:if e % 2 == 0 { // if条件后面不用写小括号 println!("{}", e);} else if e % 3 == 0 { // 但是后面的语句块必须包含在大括号之中,哪怕只有一行 println!("{} % 3 ==0", e);} else { println!(":p");} 流程控制4条件赋值因为语句本身是一个表达式,所以可以把和联合在一起来使用,也就是条件赋值:let a = if condition { 5} else { 6};当然前提是不同的分支下的语句要是一样的类型,否则编译器会检测出错误。循环的loop关键字支持创建一个循环let mut i = 0;loop { i += 1; println!("->{}", i);}基本上这就是一个死循环了。不知道为啥要定义这样一个奇葩的关键字。索性我们可以像其他编程语言一样break。值得注意的是,跟条件赋值一样,语句也是可以和一起来赋值的,像下面这样:let s = loop { i += 1; println!("->{}", i); if(i > 100) { break i; }};println!("s = {}", s); // s = 101除了这个loop外,也可以正常的像其他语言一样,使用while和for进行条件循环:while i < 1000 { // 不用写小括号 i += 1;}for e in a.iter() { // 使用for循环遍历数组 println!("{}", e); }// for i in (1..10).rev()// 使用rev()反转顺序for i in (1..10) { println!("{}", i);} rust语言的一些惯例5rust语言的一些惯例命名方式中推荐使用蛇形命名来作为方法和变量的命名方式,所有的标识符都是小写且使用下划线分隔,例如:let foo_bar = 1;fn print_info() {}