Rust语言介绍【维基百科】

维基百科链接点我

Rust是一个由Mozilla[11]主导开发的通用、编译型编程语言。它的设计准则为“安全,并发,实用”,[12][13]支持函数式并发式过程式以及面向对象的编程风格。

Rust 语言原本是 Mozilla 员工 Graydon Hoare 的私人项目,而 Mozilla 于 2009 年开始赞助这个项目[14],并且在 2010 年首次揭露了它的存在[15]。也在同一年,它的编译器源代码开始由原本的 OCaml 语言转移到用 Rust 语言,进行 bootstrapping 工作,称做 rustc[16],并于 2011 年实际完成[17]。这个可自我编译的编译器在架构上采用了 LLVM 做为它的后端。

第一个有版本号的 Rust 编译器于 2012 年 1 月发布。[18] Rust 1.0 是第一个稳定版本,于 2015 年 5 月 15 日发布。[19]

Rust 是在完全开放的情况下进行开发,并且相当欢迎社区的回馈。在 1.0 稳定版之前,语言设计也因为通过撰写 Servo 网页浏览器排版引擎和 rustc 编译器本身,而有进一步的改善。虽然它由 Mozilla 资助,但它其实是一个共有项目,有很大部分的代码是来自于社区的贡献者。[20]

设计

Rust 的设计目标之一,是要使设计大型的互联网客户端服务器的任务变得更容易[21]。因此更加强调安全性、存储器配置、以及并发处理等方面的特性。在性能上,具有额外安全保证的代码会比 C++ 慢一些,但是如果以 C++ 也手工提供保证的情况下,则两者性能上是相似的[22]

它的语法设计,与 C语言和 C++ 相当相似,区块 (block) 使用大括号隔开,流程控制的关键字如 ifelsewhile 等等。在保持相似性的同时,Rust 也加进了新的关键字,如用于模式匹配 (pattern matching) 的 match (与 switch 相似) 则是使用 C/C++ 系统编程语言的人会相对陌生的概念。尽管在语法上相似,Rust 的语义 (semantic) 和 C/C++ 非常不同。

为了提供存储器安全,它的设计不允许空指针悬空指针[23] [24] 。 数据只能通过固定的初始化形态来建构,而所有这些形态都要求它们的输入已经分析过了[25]。 Rust 有一个检查指针生命期间和指针冻结的系统,可以用来预防在 C++ 中许多的类型错误,甚至是用了智能指针功能之后会发生的类型错误。

它的类型系统直接地模仿了 Haskell 语言的 type class 概念,并把它称作“traits”,可以把它看成是一种 ad hoc 多态。Rust 的作法是通过在宣告类型变量 (type variable) 的时候,在上面加上限制条件。至于 Haskell 的高阶类型变量 (Higher-kinded polymorphism) 则还未支持。

Rust 虽然有垃圾回收系统,但非如 Java 或 .NET 平台的全自动垃圾回收。Rust 1.0已不再使用垃圾回收器,而是全面改用基于引用计数的智能指针来管理内存。

类型推导也是 Rust 提供的特性之一,使用 let 语法宣告的变量可以不用宣告类型,亦不需要初始值来推断类型。但如果在稍后的程序中从未指派任何值到该变量,编译器会发出编译时 (compile time) 错误[26]。 函数可以使用泛型化参数 (generics),但是必须绑定 Trait。没有任何方法可以使用方法或运算符,又不宣告它们的类型,每一项都必确明确定义。

Rust 的对象系统是基于三样东西之上的,即实现 (implementation)、Trait 以及结构化数据 (如 struct)。实现的角色类似提供 Class 关键字的编程语言所代表的意义,并使用 impl 关键字。继承和多态则通过 Trait 实现,它们使得方法 (method) 可以在实现中被定义。结构化数据用来定义字段。实现和 trait 都无法定义字段,并且只有 trait 可以提供继承,借以躲避 C++ 的“钻石继承问题”(菱型缺陷)。

历史

2006年,Rust作为Graydon Hoare的个人项目首次出现。

2009年,Graydon Hoare成为Mozilla雇员[14]

2010年,Rust首次作为Mozilla官方项目出现[15]。同年,Rust开始从初始编译(由OCaml写成)转变为自编译[16]

2011年,Rust成功的完成了移植[17]。Rust的自编译器采用LLVM作为其编译后端。

2012年1月20日,第一个有版本号的预览版Rust编译器发布[18]

2013年4月4日,Mozilla基金会宣布将与三星集团合作开发浏览器排版引擎Servo,此引擎将由Rust来实现[27]

2015年5月16日,Rust 1.0.0发布[28]

代码示例

下面的代码在Rust 1.3中测试通过。

Hello World

fn main() {
    println!("Hello, World!");
}

阶乘

下面是三个不同版本的阶乘函数,分别以递归循环迭代器的方法写成:

// 这个函数的if-else语句中展示了Rust中可选的隐式返回值,可用于写出更像函数式编程风格的代码
// 与C++和其他类似的语言不同,Rust中的if-else结构不是语句而是表达式,有返回值
fn recursive_factorial(n: u32) -> u32 {
    if n <= 1 {
        1
    } else {
        n * recursive_factorial(n - 1)
    }
}

fn iterative_factorial(n: u32) -> u32 {
    // 变量用`let`定义,`mut`关键字使得变量可以变化
    let mut i = 1u32;
    let mut result = 1u32;
    while i <= n {
        result *= i;
        i += 1;
    }
    result // 显式返回值,与上一个函数不同
}

fn iterator_factorial(n: u32) -> u32 {
    // 迭代器有多种用于变换的函数
    // |accum, x| 定义了一个匿名函数
    // 内联展开等优化方法会消去区间和fold,使本函数的运行效率和上一个函数相近
    (1..n + 1).fold(1, |accum, x| accum * x)
}

fn main() {
    println!("Recursive result: {}", recursive_factorial(10));
    println!("Iterative result: {}", iterative_factorial(10));
    println!("Iterator result: {}", iterator_factorial(10));
}

并发

一个简单的Rust并发示例:

use std::thread;

// 这个函数将创建十个同时并发运行的线程
// 若要验证这一点,可多次运行这个程序,观察各线程输出顺序的随机性
fn main() {
    // 这个字符串是不可变的,因此可以安全地同时被多个线程访问
    let greeting = "Hello";

    let mut threads = Vec::new();
    // `for`循环可用于任何实现了`iterator`特性的类型
    for num in 0..10 {
        threads.push(thread::spawn(move || {
            // `println!` 是一个可以静态检查格式字符串类型的宏
            // Rust的宏是基于结构的(如同Scheme)而不是基于文本的(如同C)
            println!("{} from thread number {}", greeting, num);
        }));
    }

    // 收集所有线程,保证它们在程序退出前全部结束
    for thread in threads {
        thread.join().unwrap();
    }
}
发布了142 篇原创文章 · 获赞 337 · 访问量 224万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章