Rust 笔记

2019-03-01  语言  ,  1,916

官网

官网教程及其第三方翻译版

文档查询

关键字大全

运算符大全

吸收了各种语言精华的系统级语言!牛逼就完事了!

安装篇

看别人的就好,参考

遇到了一些奇葩bug

vscode的rust(RLS)插件。。会与powershell的配置文件里的Set-Location ...冲突。。。这导致你cargo buildcargo test等统统失效。。

所以需要一个pull request...

issue

临时解决方法是,把vscodedefault shell换成cmd的而不是powershell,具体做法就是ctrl+shift+p,然后输入shell,然后选择默认的shell就好

入门笔记

  • let声明的变量名是可以复用的(Shadowing)!
use std::io;
fn main() {
    let num = 3;
    println!("{}", num);
    let mut num = String::new();
    io::stdin().read_line(&mut num)
        .expect("Failed to input");
    let num: i32 = match num.trim().parse() {
        Ok(x) => x,
        Err(_) => 0,
    };
    println!("{}", num); // type of num is int32
}
  • 类型isizeusize类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的, 32 位架构上它们是 32 位的
  • 元组数组VecHashMap;unit类型,即(),表示useless类型。。。比如可以用于Ok(())
  • Option枚举类型if-let
  • debug编译会自动检测溢出!溢出是不允许的!(不过有办法允许)参考
  • 语句和表达式严格区分,区别在与表达式的结尾没有分号,语句必须有。没有x = y = 3这种写法。参考
  • 代码块{}的值是其最后一个表达式的值
  • 循环标签牛逼!参考
fn main() {
    'outer: loop {
        println!("Entered the outer loop");

        'inner: loop {
            println!("Entered the inner loop");

            // This would break only the inner loop
            //break;

            // This breaks the outer loop
            break 'outer;
        }

        println!("This point will never be reached");
    }

    println!("Exited the outer loop");
}
  • 所有权(Ownership)的例子以及Copy trait的简单规则
  • 数据在同一个作用域里:要么只能有一个可变引用,要么只能有多个不可变引用。引用必须总是有效。参考
  • 输出一个结构体可以用{:?},但前提是这个结构体定义上边加上了#[derive(Debug)]
  • crate的各种用法参考
  • s: String是可以把&s传入到fn func(t: &str)里的,这是因为解引用强制多态,使得&s变成了&s[..]参考。同理&Vec<T>也可以传到&[T]里。
  • zip的用法
use std::collections::HashMap;

let teams  = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];

let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();
  • HashMap默认的hasher不是很快,追求性能还是去考虑库里有啥吧
  • Result的一些简写用法
  • 错误传播牛逼!有多牛逼呢?参考
fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("hello.txt");

    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut s = String::new();

    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

等价于

fn read_username_from_file() -> Result<String, io::Error> {
    let mut s = String::new();

    File::open("hello.txt")?.read_to_string(&mut s)?;

    Ok(s)
}
  • 实现 trait 时需要注意的是,只有当 trait 或者要实现 trait 的类型位于 crate 的本地作用域时,才能为该类型实现 trait。
  • 真的是怎么好怎么来
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {

可以简化为

fn some_function<T, U>(t: T, u: U) -> i32
    where T: Display + Clone,
          U: Clone + Debug
{
fn  add_one_v1   (x: u32) -> u32 { x + 1 }
let add_one_v2 = |x: u32| -> u32 { x + 1 };
let add_one_v3 = |x|             { x + 1 };
let add_one_v4 = |x|               x + 1  ;

测试

参考

CI

  • .travis.yml:
language: rust
rust:
  - stable
script:
  - cargo build --verbose --all

大全

多线程读取同一个文件的多行内容

自己摸索的第一种做法是不会清空之前的内存的方法,使用rayon

let file = File::open(path).expect(&format!("......Cannot open {}", path));
let buf = BufReader::with_capacity(1024 * 1024 * 32, file); // 缓存大小32 M
buf.lines().collect::<Vec<_>>().chunks(10000).for_each(|slice| { // 每次读10000行
    // blabla;
    slice.par_iter().enumerate().for_each(|(i, line)| { // 第 i 行,内容是line
        let line = line.as_ref().unwrap(); // 此时得到&String的line
    });
});

第二种方法是自己手写了个iterator,参考我的repo

多个闭包并行

使用rayon+join宏

macro_rules! join {
    ( < $x:ident , ) => {
        $x
    };
    ( < $x:ident , $( $xs:ident , )+ ) => {
        ( $x , join!( < $( $xs , )+ ) )
    };

    ( > $x:expr , ) => {
        ($x)()
    };
    ( > $x:expr , $( $xs:expr , )+ ) => {
        ::rayon::join( $x , || join!( > $( $xs , )+ ) )
    };

    ( @ $( let $lhs:ident = $rhs:expr ; )+ ) => {
        {
            let join!( < $( $lhs , )+ ) = join!( > $( $rhs , )+ );
            ($( $lhs ),+) // flattened tuple
        }
    };
    ( @ $( let $lhs:ident = $rhs:expr ; )* $x:expr $( , $xs:expr )*) => {
        join! { @
            $( let $lhs = $rhs ; )*
            let lhs = $x;
            $($xs),*
        }
    };

    ( $x:expr $( , $xs:expr )* ) => {
        join! { @ $x $( , $xs )* }
    };
}

然后就能

join!(
    || a.sort(),
    || b.sort(),
    || c.sort(),
    || d.sort()
);

获取rayon当前配置线程数目

use rayon::current_num_threads;

let num = current_num_threads();

使用当前crate的另一文件的宏

假如我在b.rs里写了一些宏,想在a.rs里用怎么办?

lib.rs里写上

#[rustfmt::skip]
#[macro_use]
mod b;

mod a;

顺序一定不能反!

欢迎留言>_<

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据