【Rust】语言风格

527 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

学习曲线


所有的语言都有其生产力基准线。在这个基准线上,你掌握的知识足够你使用。当到达这个点之后,想要达到技艺精湛,那就要通过项目尝试最佳实践、熟悉标准库文档(纵向)以及扩展自己的技术栈(横向)。

Python 的生产力基准线很低。所以这门语言很容易掌握,也因此很受欢迎。JavaScript 由于存在异步(Async) ,所以基准线略高一些。默认情况下,强类型语言的难度更高。

大家都说其学习曲线十分陡峭,没错,Rust 的生产力基准线更像是一个过山车。对初学者来说想要,门槛会比你之前学的高级语言更高一些。一旦你觉得自己懂了,然后深入这门语言,你就会发现自己其实一无所知。

Rust 编程风格


变量命名

Rust 的风格与 JavaScript 的略有不同:

Rust 中变量、函数和模块采用蛇形(snake case)命名(e.g. time_in_millis),而 JavaScript 中采用驼峰式(camel case)命名(e.g. timeInMillis)。

Rust 中结构(JavaScript 的对象和类的一个交集)采用大驼峰命名(e.g. CpuModule),这跟 JavaScript 是一样的。

常量都采用大写蛇形命名(capital snake case)(e.g. GLOBAL_TIMEOUT)。

括号是可选的

if (x > y) {  /* */  }
while (x > y) {  /* */  }

在不产生歧义的情况下,可以省略括号,写成:

// 这种风格是首选。
if x > y {  /* */  }
while x > y {  /* */  }

几乎所有的语句都是表达式

几乎所有的完整代码块,都会返回一个值:

显然,4 * 2 会返回一个 (8), if true { 1 } else { 0 } 也会返回 1

也就是说,可以把代码块的结果,赋值给变量,或者当做返回值用。例如:

fn main() {
    let apples = 6;
    let message = if apples > 10 {
        "Lots of apples"
    } else if apples > 4 {
        "A few apples"
    } else {
        "Not many apples at all"
    };
    println!("{}", message)  // 打印 "A few apples"  }

💡 那三行字符串并没有用 分号; 结尾。如果在其中一个加上分号会怎么样?如果给他们三个都加上分号呢?

单元类型 ()

Rust 不像 JavaScript 有 nullundefined 的概念。听起来不错,不过“无”跟那些明显存在的事物不同,它有其含义,意味着 虚无 ,尽管是一种有含义的虚无。也就是说, Rust 仍需要一个类型,可以表达“无”。

在上面例子中的第一个字符串后面,加一个分号,使得 if {} else if {} else {} 看起来是这样:

let message = if apples > 10 {
    "Lots of apples";   // ⬅ 有分号 } else if apples > 4 {
    "A few apples"
} else {
    "Not many apples at all"
};

Rust 编译不通过,报了一个错误,“ifelse 类型不匹配(if and else have incompatible types)”:

() 称为单元类型。本质上,它意为“没有值”。一个用分号结尾的表达式没有返回值,或者说,返回了 () 。Rust 看到条件判断语句的 if {} 返回了空值 (),也期待剩下的其他条件每个也返回同样类型的值,即()

隐式返回

上面我们看到一个代码块如何返回一个值。函数也不例外。函数执行的最后一行将用作函数的返回值。会经常看到一些函数没有显式的 return 语句,例如:

fn add_numbers(left: i64, right: i64) -> i64 {
    left + right   // ⬅ 没有分号 }

即等价于:

fn add_numbers(left: i64, right: i64) -> i64 {
    return left + right;
}

如果指定了一个返回值类型(即上面的 -> i64),而且意外地在最后一行使用了分号,会看到跟上面一小节一样的报错:

你可能需要花些时间来适应这样的语法。每当你看到了一个 () 的报错,那通常都是与此有关,只需要在某处增加/删除一个分号/返回值

数组类型

Rust 有数组类型。但 Rust 数组的缺点是:它们必须长度已知,而且所有的元素必须初始化。

下面这样写不行:

let mut numbers = [1, 2, 3, 4, 5];
numbers.push(6);
println!("{:?}", numbers);

数组不值得深入的原因是,你想要的可能不是数组。你想要的是 VecVecDequeVec 之于 JavaScript 的数组,正如 String 之于 JavaScript 的字符串。 Vec 可以在尾端增长和缩减, VecDeque 可以在任一个方向增长和缩减。

VecDeque 发音是 vec-deck。 Deque 意为 "Double ended queue",双端队列。

之后我们会有专门的章节介绍数组和迭代器,不过这里要知道,有一个宏来帮助你快速初始化。

let mut numbers = vec![1, 2, 3, 4, 5];   // ⬅ vec! macro numbers.push(7);
println!("{:?}", numbers);

总结


对于详细的 Rust 语法,请查看《Rust 程序设计语言》!