精华内容
下载资源
问答
  • rust实战入门到进阶(1)
    2021-05-21 17:35:16

    1、自适应安装
    (1)在Unix/Linux下,使用curl https://sh.rustup.rs -sSf | sh在Shell中运行,它自动启动安装过程:首先,下载并运行rustup-init.sh,然后,依次下载并运行rustup-init适合当前平台的可执行文件的正确版本。

    $ curl https://sh.rustup.rs -sSf | sh
    ...
    1) Proceed with installation (default)
    2) Customize installation
    3) Cancel installation
    >1
    ...
    Rust is installed now. Great!
    

    安装脚本在下次登录时自动加Rust到系统路径PATH 。
    如果想马上开始使用Rust而不是重新启动你的终端,在shell中运行以下命令来手动添加Rust到你的系统路径:

    $ source $HOME/.cargo/env
    

    也可加入下面行到 ~/.bash_profile:

    $ export PATH="$HOME/.cargo/bin:$PATH"
    

    打开https://www.rust-lang.org/tools/install安装
    更新与卸载
    $ rustup update
    $ rustup self uninstall
    (2)在Windows下,下载并运行rustup-init.exe,将自动安装正确版本。下载地址如下:
    https://www.rust-lang.org/zh-CN/tools/install
    2、独立安装,下载地址如下:
    https://forge.rust-lang.org/infra/other-installation-methods.html#standalone
    下载后执行安装文件即可。

    
    
    单元测试
    //rust-3
    fn get_distance(x1:f64,y1:f64,x2:f64,y2:f64)->f64{
    	let dis=((x1-x2).powi(2)+(y1-y2).powi(2)).sqrt();
        dis
    }
    #[test]
    fn test_get_distance(){
    	let x:f64=(1.-10.)*(1.-10.)+(2.-20.)*(2.-20.);
    	assert_eq!(get_distance(1.,2.,10.,20.),x.sqrt());
    }
    fn main() {
        println!("{}",get_distance(11.5,16.8,29.3,10.9));
    }
    
    # cargo test
       Compiling learnrust3 v0.1.0 (F:\pro\learnrust\learnrust3)
        Finished test [unoptimized + debuginfo] target(s) in 2.20s
         Running unittests (target\debug\deps\learnrust3-4f3a444115c274cb.exe)
    
    running 1 test
    test test_get_distance ... ok
    
    test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
    

    Redox是一个用Rust语言编写的类UNIX操作系统 , 它的目标是把Rust语言的创新带入到一个现代的微内核和全系列的应用程序。

    https://www.redox-os.org/zh/docs/
    Rust语言实现
    微内核设计
    包括可选的GUI程序 - Orbital
    支持Rust标准库
    MIT授权
    驱动运行在用户空间
    包括常见的Unix命令
    C程序的新移植库
    Redox source:
    https://gitlab.redox-os.org/redox-os/redox

    Redox是一个用pure Rust编写的通用操作系统。我们的目标是提供一个功能完整的类unix微内核,既安全又免费。
    我们与POSIX有适度的兼容性,允许Redox在无需移植的情况下运行许多程序。

    更多相关内容
  • Rust程序设计语言(第二版) 简体中文版
  • Discover the powerful, hidden features of Rust you need to build robust, concurrent, and fast applications About This Book ? Learn how concurrency works in Rust and why it is safe ? Get to know the ...
  • Rust程序设计语言第二版.epub格式Rust程序设计语言第二版.epub格式
  • Rust 程序设计语言(第二版).pdf 学习rust必备,rust是mozilla开发,rust的作者也是javascript的作者。
  • Rust, 作为一种通用的多范式语言(general purpose multi-paradigm language),其目标定位在C和C++一直占据主导地位的系统编程领域。 这意味着Rust可以用来编写操作系统、游戏引擎和许多对性能有相当要求的应用程序...

     

    开场白

    Rust, 作为一种通用的多范式语言(general purpose multi-paradigm language),其目标定位在C和C++一直占据主导地位的系统编程领域。

    这意味着Rust可以用来编写操作系统、游戏引擎和许多对性能有相当要求的应用程序

    同时,该语言具有非常优秀的语言表达能力 ,可以用来构建高性能的web应用程序、网络服务、类型安全的数据库对象关系映射器(ORM,Object Relational Mapper )库,还可以自顶向下的编译WebAssembly,在web上运行高效。

     

    全能高手

                                                                     

    该语言在为嵌入式平台构建安全攸关、实时应用方面也取得了不错的成绩,比如Arm中基于Cortex-M的微控制器(目前该领域由C语言主导)。

    Rust在各个领域都表现不凡,目前很难再找到另一种单一语言可以与之相比

    此外,Cloudflare、Dropbox、Chuckfish、npm等知名公司已经在其高风险(high-stakes )项目的生产中使用了它。

    Rust是一种静态的严格类型编程语言。静态属性意味着编译器在编译时可以拥有关于所有变量及其类型的信息,并在编译时完成大多数检查,这使得在运行时只需进行极少的类型检查。

    其严格性则表现在不允许类型之间的自动转换,并且不能在后续代码中将指向整数的变量指向字符串。

    正是这个属性,Rust能够对代码进行安全重构,并在编译时捕获大多数bug,而不必都等到运行时候再来报错了。

    除了高性能外,用Rust编写的程序所具备的强大表现力,使之具备高级函数风格语言的大多数特性,

    比如高阶函数(higher-order functions)惰性迭代器(lazy iterators),完全可以编译成如C/ C++程序那等高效的代码。

    在有关该语言的设计上,其所建立的原则是:编译时内存安全(compile-time memory safety)、零代价抽象(zero cost abstractions)和并发无忧(fearless concurrency)。

    下面来具体的解释以下这三大特性。

    内存安全(Compile-Time Memory Safety)

    Rust编译器可以在编译时跟踪程序中拥有资源的变量,并且能够在不使用垃圾收集器的情况下,完成所有相同目的的工作。

    这里,资源可以是内存地址、保存值的变量、共享内存引用、文件处理程序、网络套接字或数据库连接处理程序。

                               

    这意味着在运行时,不会出现在C中时有出现的---在释放、双重释放或悬空指针之后使用指针---的问题。

    在Rust中的引用类型(在其前带有&的类型)会隐式地与一个生命周期标记('foo)关联,这有时也会由程序员显式注释。

    在整个生命周期中,编译器可以跟踪代码中可以安全使用引用的位置,如果不合规,则会在编译时报告错误。

    实现这一点时,Rust根据引用上的生命周期标记来运行一种借用/引用检查算法(borrow/reference checking algorithm ),以确保已释放的内存地址不能再被访问。

    正因如此,如有其他变量正在使用该指针,则其无法被释放。基于原理层面的阐释,将在后边的文章中深入涉及。

    零代价抽象(Zero Cost Abstractions)

                              

    这个概念始于C++。

    众所周知,编程完全是为了管理复杂性而存在的,而良好的抽象有助于复杂性的管理。

    这里有一个用Rust和Kotlin(一种基于Java虚拟机(JVM)的语言)进行抽象的实例,会对高级代码的编写颇有助益,并且使其易于阅读和推理。

    该实例会比较Kotlin的流和Rust的迭代器在操作数字列表方面的作用,并反衬出Rust所提供的零代价抽象原则之优势。

    这里的抽象是为了能够使用以其他方法作为参数的方法来过滤数字,其操作思想是基于条件,而非手动循环。

    这里使用Kotlin,是因为在语法形象上与Rust相似,代码相当容易理解,这里的目标是给出一个高级的解释,因此将忽略代码中的细节,因为这个实例的全部要点是理解零代价属性。

     

    首先,看下Kotlin中的代码:

         

    这里创建了一个数字流(第6行)并调用一个方法链(filtermap)来转换元素,以收集偶数的平方。这些方法能够采用闭包或函数(即第八行:it -> it * it )转换集合中的每个元素。

    在函数式语言中,当在流/迭代器上调用这些方法时,对于每次这样的调用,都会创建一个中间对象来保存与正在执行的操作相关的任何状态或元数据。

    因此,evens和evenSquares将是分配在JVM堆上的两个不同的中间对象。显然,在堆上分配东西会导致内存开销,这就是在Kotlin的使用中必须要为抽象付出的额外代价!

     

    这里对平方和偶数值打印如下:

                                    

    @后面的十六进制值是JVM上对象的不同的哈希代码,可见是不同的对象。

     

    Rust中,做同样的事情如下:

        

       

    在第2行调用vec![]在堆上创建一个数字列表,然后调用into_iter()使其成为一个数字迭代器/流,而into_iter()方法从一个集合(这里Vec是一个有符号的32位整数列表)中创建一个封装迭代器类型:IntoIter([1,2,3,4,5,6,7,8,9,10])

    这个迭代器类型引用原始的数字列表,然后执行过滤器(filter)和映射转换(map,第3行和第4行),就像我们在Kotlin中所做的那样。第7行和第8行打印了evens和even_squares的类型,如下所示(为了简洁起见,省略了一些细节):

                         

    可见,中间对象Filter和Map是基本迭代器结构上的封装器类型(不是在堆上分配的),其本身是一个封装器,已经装着对第2行原始数字列表的引用了。

    第4行和第5行上的封装器结构分别是在调用filter和map时创建的,它们之间没有任何指针进行间接寻址,也没有强加任何像Kotlin的那样的堆分配开销

    所有这些都归结为高效的汇编代码,相当于手动写循环的效果。

     

    结语

    下一篇,将会介绍Rust在并发方面的优势,以及同其它编程语言的华山论剑

    展开全文
  • Rust Cookbook_精通系列

    2018-01-21 10:15:01
    系统编程语言Rust,没有GC,性能极高。值得学习的好语言!
  • Rust入门中文指南.pdf

    2019-12-31 11:33:06
    Rust中文入门指南 Rust 程序设计语言(第二版 & 2018 edition)简体中文版 一步一步通过例子学会Rust编程语言
  • ndarray 依赖 Cargo.toml 文件加入: [dependencies] ndarray = "0.15.3" ndarray 具体函数可参考 ...一、向量Vec 与 Array互转 extern crate ndarray; use ndarray::{concatenate, s, Axis, Array, Array2, Array3};...

    ndarray 依赖

    Cargo.toml 文件加入:

    [dependencies]
    ndarray = "0.15.3"
    

    一、向量Vec 与 Array互转

    extern crate ndarray;
    use ndarray::{concatenate, s, Axis, Array, Array2, Array3, arr2, arr3};
    fn main(){
    	let vec1 = vec![[1., 2., 3., 4.],[1.,2.,3.,4.]];
    	let array = Array::from_vec(vec1.clone());
    	let array2: Array2<f64>  = arr2(&vec1.clone());
    	println!("array:{:?}",array);
    	println!("array2:{:?}",array2);
    	println!("to_vec:{:?}",array.to_vec());
        let mut res_to_vec = vec![]; 
        for row in array2.genrows(){
            res_to_vec.push(row.to_vec());
        }
    	println!("to_vec:{:?}",res_to_vec);
    }
    

    运行结果:

    array:[[1.0, 2.0, 3.0, 4.0], [1.0, 2.0, 3.0, 4.0]], shape=[2], strides=[1], layout=CFcf (0xf), const ndim=1
    array2:[[1.0, 2.0, 3.0, 4.0],[1.0, 2.0, 3.0, 4.0]], shape=[2, 4], strides=[4, 1], layout=Cc (0x5), const ndim=2
    array_to_vec:[[1.0, 2.0, 3.0, 4.0], [1.0, 2.0, 3.0, 4.0]]
    array2_to_vec:[[1.0, 2.0, 3.0, 4.0], [1.0, 2.0, 3.0, 4.0]]
    

    注意,from_vec 不管传几维,最终都是转一维的数组,ndim=1。
    二、Array多维数组生成
    基于其维度使用Array2和Array3来对多维进行操作,ones是生成全一多维数组,zeros生成全零多维数组,根据其维度选择Array2或者Array3,linspace是生成一维列表,from_elem可以生成特定的多维数组,其最后一个参数即为内部值

    let array = Array::linspace(0., 10., 3);
    let array1 = Array2::<i64>::ones((1,2));
    let array2 = Array3::<i64>::zeros((1, 2, 3));
    let array3 = Array::from_elem((1, 2), 7.);
    let array4 = Array::from_elem((1, 2, 3), 7.);
    println!("array:{:?}",array);
    println!("array1:{:?}",array1);
    println!("array2:{:?}",array2);
    println!("array3:{:?}",array3);
    println!("array4:{:?}",array4);
    

    运行结果:

    array:[0.0, 5.0, 10.0], shape=[3], strides=[1], layout=CFcf (0xf), const ndim=1
    array1:[[1, 1]], shape=[1, 2], strides=[2, 1], layout=CFcf (0xf), const ndim=2
    array2:[[[0, 0, 0],[0, 0, 0]]], shape=[1, 2, 3], strides=[6, 3, 1], layout=Cc (0x5), const ndim=3
    array3:[[7.0, 7.0]], shape=[1, 2], strides=[2, 1], layout=CFcf (0xf), const ndim=2
    array4:[[[7.0, 7.0, 7.0],[7.0, 7.0, 7.0]]], shape=[1, 2, 3], strides=[6, 3, 1], layout=Cc (0x5), const ndim=3
    

    三、Array多维数组索引和切片
    3.1、二维索引与三维索引

    let mut vec2 = vec![[1,2,3],[4,5,6],[7,8,9],[10,11,12]];
    let mut vec3 = vec![[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]];
    let array2 = arr2(&vec2);
    let array3 = arr3(&vec3);
    println!("(1,2):{}",array2[[1,2]]);
    println!("(1,1,1):{}",array3[[1,1,1]]);
    

    运行结果:

    (1,2):6
    (1,1,1):11
    

    3.2、切片
    二维的slice s![x,y],表示行和列,而三维的slice s![x,y,z],其中的x是代表第几个矩阵,y,z表示矩阵的行和列。

    let mut vec2 = vec![[1,2,3],[4,5,6],[7,8,9],[10,11,12]];
    let mut vec3 = vec![[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]];
    let array2 = arr2(&vec2);
    let array3 = arr3(&vec3);
    println!("slice:{:?}",array2.slice(s![..,0..2]));
    println!("slice:{:?}",array3.slice(s![..,0..1,..]));
    

    运行结果:

    slice:[[1, 2],[4, 5],[7, 8],[10, 11]], shape=[4, 2], strides=[3,1], layout=c (0x4), const ndim=2
    slice:[[[1, 2, 3]],[[7, 8, 9]]], shape=[2, 1, 3], strides=[6,0, 1], layout=c (0x4), const ndim=3
    

    四、Array多维数组基本运算
    4.1、多维数组转置与二维矩阵点乘
    转置.t(); 点乘 .dot(& );

    let mut vec2 = vec![[1,2,3],[4,5,6],[7,8,9],[10,11,12]];
    let mut vec3 = vec![[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]];
    let array2 = arr2(&vec2);
    let array3 = arr3(&vec3);
    println!("t:{:?}",array2.t());
    println!("t{:?}",array3.t());
    println!("二维矩阵点乘{:?}",array2.dot(&array2.t().clone()));
    

    运行结果:

    t:[[1, 4, 7, 10],[2, 5, 8, 11],[3, 6, 9, 12]], shape=[3, 4], strides=[1, 3], layout=Ff (0xa), const ndim=2
    t[[[1, 7], [4, 10]], [[2, 8],[5, 11]],[[3, 9],[6, 12]]], shape=[3, 2, 2], strides=[1, 3, 6], layout=Ff (0xa), const ndim=3
    二维矩阵点乘[[14, 32, 50, 68], [32, 77, 122, 167], [50, 122, 194, 266],[68, 167, 266, 365]], shape=[4, 4], strides=[4, 1], layout=Cc (0x5), const ndim=2
    

    4.2、多维数组基本运算
    矩阵之间的加、乘、除、取余等操作,按位加、乘、除、取余等操作

    let mut vec2 = vec![[1,2,3],[4,5,6],[7,8,9],[10,11,12]];
    let mut vec21 = vec![[1,2,3],[4,5,6],[7,8,9],[10,11,12]];
    let mut array2 = arr2(&vec2);
    let mut array21 = arr2(&vec21);
    println!("按位相乘{:?}",array2.clone() * array21.clone());
    println!("按位相加{:?}",array2.clone() + array21.clone());
    println!("按位相除{:?}",array2.clone() / array21.clone());
    println!("按位加元素{:?}",array2.clone() + 3);
    println!("按位乘元素{:?}",array2.clone() * 4);
    println!("按位取余元素{:?}",array2.clone() % 5);
    

    运行结果:

    按位相乘[[1, 4, 9],[16, 25, 36], [49, 64, 81],[100, 121, 144]], shape=[4, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2
    按位相加[[2, 4, 6],[8, 10, 12],[14, 16, 18],[20, 22, 24]], shape=[4, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2
    按位相除[[1, 1, 1],[1, 1, 1],[1, 1, 1],[1, 1, 1]], shape=[4, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2
    按位加元素[[4, 5, 6],[7, 8, 9],[10, 11, 12],[13, 14, 15]], shape=[4, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2
    按位乘元素[[4, 8, 12],[16, 20, 24],[28, 32, 36],[40, 44, 48]], shape=[4, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2
    按位取余元素[[1, 2, 3],[4, 0, 1], [2, 3, 4],[0, 1, 2]], shape=[4, 3], strides=[3, 1], layout=Cc (0x5), const ndim=2
    

    4.3、矩阵聚合、均值

    let vec1 = vec![[1., 2., 3., 4.],[1.,2.,3.,4.]];
    let array2:Array2<f64> = arr2(&vec1.clone());
    println!("sum:{:?}",array2.sum());
    println!("mean:{:?}",array2.sum()/array2.len() as f64);
    

    运行结果:

    sum:20.0
    mean:2.5
    

    4.4、矩阵求逆和求解
    Cargo.toml 添加:
    ndarray-linalg = “0.14.1”
    求解Ax=B,类似可以求A的逆,是基于ndarray

    #[macro_use]
    extern crate ndarray;
    extern crate ndarray_linalg;
    
    use ndarray::prelude::*;
    use ndarray_linalg::Solve;
    
    let a: Array2<f64> = array![[3., 2., -1.], [2., -2., 4.], [-2., 1., -2.]];
    let b: Array1<f64> = array![1., -2., 0.];
    let x = a.solve_into(b).unwrap();
    assert!(x.abs_diff_eq(&array![1., -2., -2.], 1e-9));
    

    不过我没运行成功,error link 就忽略了

    展开全文
  • 为什么要使用 Rust 语言?Rust 语言的优势在哪里?

    万次阅读 多人点赞 2021-01-06 14:21:57
    Rust 是一种采用过去的知识解决将来的问题的技术。” ——Graydon Hoare Rust 是一种快速、高并发、安全且具有授权性的编程语言,最初由 Graydon Hoare 于2006 年创造和发布。现在它是一种开源语言,主要由 Mozilla...
    Rust 是一种采用过去的知识解决将来的问题的技术。” ——Graydon Hoare

    Rust 是一种快速、高并发、安全且具有授权性的编程语言,最初由 Graydon Hoare 于2006 年创造和发布。现在它是一种开源语言,主要由 Mozilla 团队和许多开源社区成员共同维护和开发。

    虽然 Rust 是一种通用的多范式语言,但它的目标是 C 和 C++占主导地位的系统编程领域。这意味着你可以使用 Rust 编写操作系统、游戏引擎和许多性能关键型应用程序。同时,它还具有足够的表现力,你可以使用它构建高性能的 Web 应用程序、网络服务,类型安全的数据库对象关系映射(Object Relational Mapping,ORM)库,还可以将程序编译成WebAssembly 在 Web 浏览器上运行。Rust 还在为嵌入式平台构建安全性优先的实时应用程序方面获得了相当大的关注,例如 Arm 基于 Cortex-M 的微控制器,目前该领域主要由 C语言主导。Rust 因其广泛的适用性在多个领域都表现良好,这在单一编程语言中是非常罕见的。

    Rust 作为一门静态和强类型语言而存在。静态属性意味着编译器在编译时具有所有相关变量和类型的信息,并且在编译时会进行大量检查,在运行时只保留少量的类型检查。它的强类型属性意味着不允许发生诸如类型之间自动转换的事情,并且指向整数的变量不能在代码中更改为指向字符串。例如在 JavaScript 等弱类型语言中,你可以轻松地执行类似“two = "2"; two = 2 + two;”这样的操作。JavaScript 在运行时将 2 的类型弱化为字符串,因此会将 22 作为字符串存储到变量 two 中,这与你的意图完全相反并且毫无意义。在 Rust 中,与上述代码意义相同的代码是“let mut two = "2"; two = 2 + two;”,该代码将会在编译时捕获异常,并提示信息:“cannot add '&str' to '{integer}'”。

    因此,强类型属性使 Rust 可以安全地重构代码,并在编译时捕获大多数错误,而不是在运行时出错。用 Rust 编写的程序表现力和性能都非常好,因为使用它你可以拥有高级函数式语言的大部分特性,例如高阶函数和惰性迭代器,这些特性使你可以编译像 C/C++程序这样高效的程序。它的很多设计决策中强调的首要理念是编译期内存安全、零成本抽象和支持高并发。让我们来详细说明这些理念。

    编译期内存安全:Rust 编译期可以在编译时跟踪程序中资源的变量,并在没有垃圾收集器(Garbage Collectors,GC)的情况下完成所有这些操作。

    这意味你不会遇到在 free、double free 命令之后调用指针,或者运行时挂起指针等“臭名昭著”的问题。Rust 中的引用类型(类型名称前面带有&标记的类型)与生命周期标记隐式关联('foo),有时由程序员显式声明。在生命周期中,编译器可以跟踪代码中可以安全使用的位置,如果它是非法的,那么会在编译期报告异常。为了实现这一点,Rust 通过这些引用上的生命周期标签来运行借用/引用检查算法,以确保你永远不能访问已释放的内存地址。这样做也可以防止你释放被其他某些变量调用的任何指针。

    零成本抽象:编程的目的就是管理复杂性,这是通过良好的抽象来实现的。接下来让我们来看一个 Rust 和 Kotlin 的良好抽象示例。抽象让我们能够编写高级并且易于阅读和推断的代码。我们将比较 Kotlin 的流和 Rust 的迭代器在处理数字列表时的性能,并参照 Rust提供的零成本抽象原则。这里的抽象是指能够使用以其他方法作为参数的方法,根据条件过滤数字而不使用手动循环。在这里引入 Kotlin 是因为它看上去和 Rust 存在相似性。代码很容易理解,我们的目标是给出更高层面的解释,并对代码中的细节进行详细阐述,因为这个示例的重点是理解零成本特性。

    首先,我们来看 Kotlin 中的代码:

    1. import java.util.stream.Collectors  
    2.  
    3. fun main(args: Array<String>)  
    4. {  
    5.     //创建数字流 
    6.     val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).stream()  
    7.     val evens = numbers.filter { it -> it % 2 == 0 }  
    8.     val evenSquares  = evens.map { it -> it * it }  
    9.     val result = evenSquares.collect(Collectors.toList())  
    10.    println(result)       // prints [4,16,36,64,100]  
    11. 
    12.    println(evens) 
    13.    println(evenSquares) 
    14. }

    我们创建了一个数字流(第 6 行)并调用了一系列方法(filter 和 map)来转换元素, 以收集仅包含偶数的序列。这些方法可以采用闭包或函数(第 8 行中的“ it -> it * it”)来转换集合中的元素。在函数式编程语言中,当我们在流/迭代器上调用这些方法时,对于每个这样的调用,该语言会创建一个中间对象来保存与正在执行的操作有关的任何状态或元数据。因此,evens 和 evenSquares 将在 JVM 堆上分配两个不同的中间对象。在堆上分配资源将会产生内存开销,这是我们在 Kotlin 中为抽象必须额外付出的代价。

    当我们输出 evens 和 evenSquares 的值时,确实得到了两个不同的对象,如下所示:

    java.util.stream.ReferencePipeline$Head@51521cc1  
    java.util.stream.ReferencePipeline$3@1b4fb997 

    @之后的十六进制值是 JVM 对象的哈希值。由于哈希值不同,所以它们是不同的对象。在 Rust 中,我们会做相同的事情:

    1. fn main() {  
    2.     let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter();  
    3.     let evens = numbers.filter(|x| *x % 2 == 0);  
    4.     let even_squares = evens.clone().map(|x| x * x);  
    5.     let result = even_squares.clone().collect::<Vec<_>>();  
    6.     println!("{:?}", result); // 输出 [4,16,36,64,100]  
    7.     println!("{:?}\n{:?}", evens, even_squares);  
    8. } 

    接下来将解释上述代码的细节。在第 2 行中,我们调用 vec![]创建一个数字列表,然 后调用 into_iter()方法使其成为一个数字的迭代器/流。使用 into_iter()方法从集合中创建 了一个包装器的迭代器类型(这里 Vec<i32>是一个有符号的 32 位整数列表),即 IntoIter([1,2,3,4,5,6, 7,8,9,10]),此迭代器类型引用原始的数字列表。然后我们执行 filter 和 map 转换(第 3 行和第 4 行),就像我们在 Kotlin 中所做的那样。第 7 行输出 evens 和 even_squares 的类型,如下所示(为了简洁,省略了一些细节):

    evens:        Filter { iter: IntoIter( <numbers> ) }  
    even_squares: Map { iter: Filter { iter: IntoIter( <numbers> ) }} 

    中间对象 Filter 和 Map 是基础迭代器结构上的包装器类型(未在堆上分配),它本身是一个包装器,包含对第 2 行的原始数字列表的引用。第 4 行和第 5 行的包装器结构在分别调用 filter 和 map 时创建,它们之间没有任何指针解引用,并且不会像 Kotlin 那样产生堆分配的开销。所有这些可归结为高效的汇编代码,这相当于使用循环(语句)的手动编写版本。

    支持高并发:当我们说 Rust 是并发安全的时,其含义是该语言具有应用程序接口(Application Programming Interface,API)和抽象能力,使得编写正确和安全的并发代码变得非常容易。而在 C++中,并发代码出错的可能性非常大。在 C++中同步访问多个线程的数据时,需要在每次进入临界区时调用 mutex.lock(),并在退出它时调用 mutex.unlock():

    // C++  
    mutex.lock();          // 互斥锁锁定 
     // 执行某些关键操作 
    mutex.unlock();        // 执行完毕

    在大量开发人员共同协作的大型代码库中,你可能会忘记在多线程访问共享对象之前调用 mutex.lock(),这可能导致数据访问冲突。在其他情况下,你可能忘记解开互斥锁(Mutex),并使其他想要访问数据的线程一直处于等待状态。

    Rust 对此有不同的处理方式。在这里,你将数据包装成 Mutex 类型,以确保来自多个线程的数据进行同步可变访问:

    // Rust  
    use std::sync::Mutex;  
    fn main() {  
        let value = Mutex::new(23);  
        *value.lock().unwrap() += 1;         // 执行一些修改 
    }                                        // 这里自动解锁

    在上述代码中,我们能够在变量 value 调用 lock()方法之后修改数据。Rust 采用了保护共享数据自身,而不是代码的概念。Rust 与 Mutex 和受保护的数据的交互并不是独立的,这和 C++中的情况一样。你无法在 Mutex 类型不调用 lock()方法的情况下访问内部数据。

    那么 lock()方法的作用是什么?调用 lock()方法之后会返回一个名为 MutexGuard 的东西,它会在变量超出作用域范围之后自动解除锁定,它是 Rust 提供的众多安全并发抽象之一。

    另一个新颖的想法是标记特征的概念,它在编译期验证,并确保在并发代码中同步和安全地访问数据,第 4 章详细介绍了该特征。类型会被称为 Send 和 Sync 的标记特征进行注释标记,以指示它们是否可以安全地发送到线程或者在线程之间共享。当程序向线程发送值时,编译器会检查该值是否实现了所需的标记特征,如果没有,则禁止使用该值。通过这种方式,Rust 允许你毫无顾虑地编写并发代码,编译器在编译时会捕获多线程代码中的异常。

    编写并发代码已经很难了,使用 C/C++会让它变得更加困难和神秘。当前 CPU 没有获得更多的时钟频率;相反,我们添加了更多内核。因此,并发编程是正确的发展方向。Rust 使得编写并发代码变得轻而易举,并且降低了编写安全的并发代码的门槛。

    Rust 还借鉴了 C++的 RAII 原则用于资源初始化,这种技术的本质是将资源的生命周期和对象的生命周期绑定,而堆分配类型的解除分配是通过执行 drop 特征上的 drop()方法实现的。当变量超出作用域时,程序会自动调用此方法。它还用 Result 和 Option 类型替代了空指针的概念,我们将在第 6 章对此进行详细介绍。这意味着 Rust 不允许代码中出现null/undefined 的值,除非通过外部函数接口与其他语言交互,以及使用不安全代码时。该语言还强调组合,而不是继承,并且有一套特征系统,它由数据类型实现,类似于 Haskell的类型类,也被称为加强型的 Java 接口。

    但同样重要的是,Rust 社区非常活跃和友好。该语言包含非常全面的文档,可以在Rust 官网中找到。Rust 在 Stack Overflow 的开发者调查上连续 3 年(2016 年、2017 年和2018 年)被评为最受欢迎的编程语言,因此编程社区对它非常青睐。总而言之,如果你希望编写具有较少错误的高性能软件,又希望感受当前流行语言的特性和极佳的社区文化, 那么 Rust 应该是一个不错的选择。

    推荐阅读

    精通Rust 第2版

     

    • 自学教程书籍,学习Rust编程语言基础
    • 掌握更高端的编程范式,成就高段位的编程极客。

    Rust是一门系统编程语言,是支持函数式、命令式以及泛型等编程范式的多范式语言。Rust在语法上和C++类似。Rust快速、可靠、安全,它提供了甚至超过C/C++的性能和安全保证,同时它也是一种学习曲线比较平滑的热门编程语言。

    本书内容共17章,由浅入深地讲解Rust相关的知识,涉及基础语法、软件包管理器、测试工具、类型系统、内存管理、异常处理、高级类型、并发模型、宏、外部函数接口、网络编程、HTTP、数据库、WebAssembly、GTK+框架和GDB调试等重要知识点。

    本书适合想学习Rust编程的读者阅读,希望读者能够对C、C++或者Python有一些了解。书中丰富的代码示例和详细的讲解能够帮助读者快速上手,高效率掌握Rust编程。

    展开全文
  • Rust 的优点是什么?

    千次阅读 2021-06-09 09:31:40
    Rust是一种快速、高并发、安全且具有授权性的编程语言,最初由Graydon Hoare于2006年创造和发布。现在它是一种开源语言,主要由Mozilla团队和许多开源社区成员共同维护和开发。它的第一个稳定版本于2015年5月发布,...
  • Rust同其前辈以及同侪一比,其勃勃野心也真的配得上其能力之卓越。 上一篇介绍了该语言的三大特色中的内存安全(compile-time memory safety)、零代价抽象(zero cost abstractions), 在本篇中,继续讲第三个---...
  • rust 官方教程 中文版

    2015-12-14 10:48:30
    rust 官方教程 中文版 本作品采用 知识共享署名 - 相同方式共享 4.0 国际许可协议 进行许可。 Rust 官方教程 中文版 本文档为 The Rust Programming Language 的中文翻译。 欢迎在 GitHub 上为本文档做出贡献。 ...
  • 腐蚀Rust怎么玩?正式版将于2月8日正式发售,体验版已经发售多年了,想必不少喜欢的玩家都有体验过,今天给大家带来了“chnodon”分享的腐蚀Rust新手入门教学图文攻略,一起来看下吧。新手入门教学图文攻略如下图为...
  • Rust与网络编程:同步网络I/O

    千次阅读 2021-02-19 11:22:08
    Rust的标准库网络原语为套接字提供相同的同步API。要了解这个模型的实际应用,我们将不局限于实现一个echo服务器,接下来我们会构建一个Redis的精简版本。Redis是一种数据结构服务器,通常用作内存数据存储。Redis...
  • 关注了就能看到更多这么棒的文章哦~The Rust for Linux projectBy Jonathan CorbetSeptember 16, 2021KangrejosDeepL ...
  • Rust中,常会用到的3种指针有哪些?

    千次阅读 2021-01-31 14:47:12
    Rust中,我们主要会用到3种指针。 5.8.1 引用—— 安全的指针 在介绍借用时已经详细阐述了这类指针。引用类似于C语言中的指针,但同时会检查它们的正确性。它们永远不会为空值,并且指向拥有某些数据的变量。...
  • 腐蚀Rust怎么玩?正式版将于2月8日正式发售,体验版已经发售多年了,想必不少喜欢的玩家都有体验过,今天给大家带来了“chnodon”分享的腐蚀Rust新手入门教学图文攻略,一起来看下吧。新手入门教学图文攻略如下图为...
  • 将造好的设计图纸和锤子放在快捷栏,先用建筑设计图建造地基,切换到建筑设计图之后,按住鼠标右键,可以选择将要建造的项目,建筑建造学后期我们再详细讨论,目前就以简单的2*2正方形结构为示范。...
  • 其实大部分编程语言都是相通的,熟练掌握一门编程语言,能...所以我认为精通C语言能在一定程度上,帮助我们快速上手Rust。 那么再换个问法,精通C语言就一定能学会或者学好Rust吗?这个可真说不准。Rust吸收了C+...
  • 木门过于脆弱,我们直接建造铁门,建造铁门和密码锁需要用到金属碎片,而煅烧金属矿石又需要熔炉,而做熔炉又需要用到低级燃料,所以我们去采集一些地基燃料。低级燃料有两种获取方法,1.击杀动物后用斧头砍动物尸体...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,097
精华内容 438
关键字:

精通rust