吸收了各种语言精华的系统级语言!牛逼就完事了!
安装篇
看别人的就好,参考
遇到了一些奇葩bug
vscode的rust(RLS)插件。。会与powershell的配置文件里的Set-Location ...冲突。。。这导致你cargo build、cargo test等统统失效。。
所以需要一个pull request...
临时解决方法是,把vscode的default 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
}- 类型
isize和usize类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的, 32 位架构上它们是 32 位的 - 元组;数组;Vec;HashMap;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();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;顺序一定不能反!