吸收了各种语言精华的系统级语言!牛逼就完事了!
安装篇
看别人的就好,参考
遇到了一些奇葩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;
顺序一定不能反!