1、if
1. if-else if -else
fn main() {
let n = 5;
if n < 0 {
print!("{} is negative", n);
} else if n > 0 {
print!("{} is positive", n);
} else {
print!("{} is zero", n);
}
}
2. 表达式语句
fn main()
{
let x = 5;
let y = if x == 5 { 10 } else { 15 };
let z = if x == 5 { 10 } else if x == 6 { 15 } else if x == 7 { 20 } else { 25 };
}
2、for
1. for(x = 0; x < 10; x++);
fn main() {
for x in 0..10 {
println!("{}", x); // x: i32
}
}
➜ main make
rustc main.rs
./main
0
1
2
3
4
5
6
7
8
9
➜ main
2. for-in 迭代
fn main()
{
for var in [10; 5].iter() {
print!("{:?} ", var)
}
println!("");
}
3、loop
1. loop 死循环
fn main() {
let mut n = 1;
loop {
n += 1;
if n == 5 {break};
}
}
2. loop嵌套
fn main()
{
// 外层喜欢循环,使用outer标记符
'outer: loop {
println!("Entered the outer loop");
// 内层喜欢循环,使用inner标记符
'inner: loop {
println!("Entered the inner loop");
break 'outer; // 结束外层循环
}
println!("This point will never be reached");
}
println!("Exited the outer loop");
}
➜ main make
rustc main.rs
warning: unreachable statement
--> main.rs:12:5
|
12 | println!("This point will never be reached");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unreachable_code)] on by default
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
./main
Entered the outer loop
Entered the inner loop
Exited the outer loop
➜ main
4、while(条件) {}
fn main() {
let mut n = 1;
while n < 101 {
if n % 15 == 0 {
println!("fizzbuzz");
} else if n % 3 == 0 {
println!("fizz");
} else if n % 5 == 0 {
println!("buzz");
} else {
println!("{}", n);
}
n += 1;
}
}
5、match
1. 类似switch-case语法结构
fn main() {
let day = 5;
match day {
0 | 6 => println!("weekend"), // case 0和6具体值
1 ... 5 => println!("weekday"), // case [1,5] 范围
_ => println!("invalid"), // default
}
}
➜ main make
rustc main.rs
./main
weekday
➜ main
2. 使用@
绑定进入case项的值
fn main() {
let x = 1;
match x {
e @ 1 ... 5 => println!("got a range element {}", e),
_ => println!("anything"),
}
}
3. 使用ref
绑定进入case项值的引用
fn main() {
let x = 5;
let mut y = 5;
match x {
// the `r` inside the match has the type `&i32`
ref r => println!("Got a reference to {}", r),
}
match y {
// the `mr` inside the match has the type `&i32` and is mutable
ref mut mr => println!("Got a mutable reference to {}", mr),
}
}
4. case 元祖
fn main() {
let pair = (0, -2);
match pair {
(0, y) => println!("x is `0` and `y` is `{:?}`", y),
(x, 0) => println!("`x` is `{:?}` and y is `0`", x),
_ => println!("It doesn't matter what they are"),
}
}
➜ main make
rustc main.rs
./main
x is `0` and `y` is `-2`
➜ main
5. case struct
struct Point {
x: i32,
y: i32,
}
fn main() {
let origin = Point { x: 1, y: 2 };
// 获取Point实例成员x的值
match origin {
Point { x:1, .. } => println!("x == 1"),
// Point { .. , y:2 } => println!("y == 2"), 不能比较后面的值
_ => println!("It doesn't matter what they are"),
}
}
➜ main make
rustc main.rs
warning: field is never used: `y`
--> main.rs:3:3
|
3 | y: i32,
| ^^^^^^
|
= note: #[warn(dead_code)] on by default
./main
x == 1
➜ main
6. case enum
enum OptionalInt {
Value(i32),
Missing,
}
fn main()
{
let x = OptionalInt::Value(5);
match x {
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
OptionalInt::Value(..) => println!("Got an int!"),
OptionalInt::Missing => println!("No such luck."),
_ => println!("It doesn't matter what they are"),
};
}
➜ main make
rustc main.rs
./main
Got an int!
➜ main
6、if let 可选值解包
fn main()
{
// Some()可选值
let number = Some(7);
// if let 解包
if let Some(i) = number {
println!("Matched {:?}!", i);
} else {
println!("Didn't match a number!");
}
}
➜ main make
rustc main.rs
./main
Matched 7!
➜ main
7、while let
fn main()
{
// 可选值
let mut optional = Some(0);
// Some(0) => Some(i) ==> i == 0
while let Some(i) = optional {
if i > 9 {
println!("Greater than 9, quit!");
optional = None; // 可选值赋值为None
} else {
println!("`i` is `{:?}`. Try again.", i);
optional = Some(i + 1); // 可选值+1后,继续打包为可选值
}
}
}
➜ main make
rustc main.rs
./main
`i` is `0`. Try again.
`i` is `1`. Try again.
`i` is `2`. Try again.
`i` is `3`. Try again.
`i` is `4`. Try again.
`i` is `5`. Try again.
`i` is `6`. Try again.
`i` is `7`. Try again.
`i` is `8`. Try again.
`i` is `9`. Try again.
Greater than 9, quit!
➜ main
8、函数
1. 全局函数
#[allow(dead_code)] // 禁用无效代码检查
fn add_one(x: i32) -> i32 {
x + 1
}
fn main()
{
println!("{}", add_one(9));
}
➜ main make
rustc main.rs
./main
10
➜ main
2. 函数抛异常
fn diverges() -> ! {
panic!("This function never returns!");
}
fn main()
{
diverges();
}
➜ main make
rustc main.rs
./main
thread 'main' panicked at 'This function never returns!', main.rs:2:3
note: Run with `RUST_BACKTRACE=1` for a backtrace.
make: *** [all] Error 101
➜ main
其中panic!
是一个宏,使当前执行线程崩溃并打印给定信息。
3. 匿名函数
1. 简单使用
fn main()
{
let num = 5;
let plus_num = |x: i32| x + num; // 默认 return (x + num);
println!("{}", plus_num(10));
}
➜ main make
rustc main.rs
./main
15
➜ main
2. move让闭包获取外部变量的所有权
fn main()
{
let mut num = 5;
println!("{}", num);
{
let mut add_num = move |x: i32| {num += x; num}; // 闭包通过move获取了num的所有权
println!("{}", add_num(7));
println!("{}", num);
}
println!("{}", num);
}
➜ main make
rustc main.rs
./main
5
12
5
5
➜ main
4. 高阶函数
1. 直接调用函数
fn add_one(x: i32) -> i32 {
x + 1
}
fn main() {
// 直接调用函数
let f0 = add_one(2i32) * 2;
println!("{}", f0);
}
➜ main make
rustc main.rs
./main
6
➜ main
2. 函数作为参数传递
fn add_one(x: i32) -> i32 {
x + 1
}
// where 控制模板参数F的类型是【Fn(i32) -> i32】
fn apply(f: F, y: i32) -> i32 where F: Fn(i32) -> i32
{
f(y) * y
}
fn main() {
// 将add_one函数作为参数传递给apply()
let f1 = apply(add_one, 2);
println!("{}", f1);
// 将add_one赋值给函数指针变量,再传递给apply()
let transform: fn(i32) -> i32 = add_one;
let f2 = apply(transform, 2);
println!("{}", f2);
}
➜ main make
rustc main.rs
./main
6
6
➜ main
3. 闭包作为函数参数
// where 控制模板参数F的类型是【Fn(i32) -> i32】
fn apply(f: F, y: i32) -> i32 where F: Fn(i32) -> i32
{
f(y) * y
}
fn main() {
// 定义闭包,再传递闭包给函数
let closure = |x: i32| x + 1;
let f1 = apply(closure, 2);
// 直接传递闭包
let f2 = apply(|x| x + 1, 2);
println!("{}, {}", f1, f2);
}
➜ main make
rustc main.rs
./main
6, 6
➜ main
4. 返回Box打包的闭包
// 返回值为【Fn 函数名(x: i32) -> i32】函数类型的指针
fn factory(x: i32) -> Box i32> {
Box::new(move |y| x + y)
}
fn main() {
let box_fn = factory(1i32);
let b0 = box_fn(2i32) * 2;
let b1 = (*box_fn)(2i32) * 2;
let b2 = (&box_fn)(2i32) * 2;
println!("{}, {}, {}", b0, b1, b2);
}
➜ main make
rustc main.rs
./main
6, 6, 6
➜ main
9、宏定义
1. 定义宏指令与调用宏指令
eg1
// 宏指令定义
macro_rules! foo {
// 左侧匹配任意的字符串 => {{要执行的语句}};
( $( $x:expr ), * ) => {{println!("hello")}};
}
fn main() {
foo!(); // 宏指令调用,区别于函数调用,使用!符号
foo!(1);
foo!(1,2);
foo!(hello);
}
➜ main make
rustc main.rs
./main
hello
hello
hello
hello
➜ main
eg2
macro_rules! foo {
() => (fn x() { println!("hello") });
}
fn main() {
foo!(); // 替换为 (fn x() { println!("hello") });
x();
}
➜ main make
rustc main.rs
./main
hello
➜ main
eg3
macro_rules! foo {
($v:ident) => (let $v = 10);
}
fn main() {
foo!(x); //
println!("{}", x);
}
➜ main make
rustc main.rs
warning: expected `;`, found ``
--> main.rs:3:27
|
3 | ($v:ident) => (let $v = 10);
| ^^
...
7 | foo!(x); //
| -------- in this macro invocation
|
= note: This was erroneously allowed and will become a hard error in a future release
./main
10
➜ main
运行虽然正常,但是会报警告,不建议通过宏定义替换为变量定义。
3. 常规宏指令的模式匹配
macro_rules! my_print {
// ( $( $x:expr ),* )
// => $( $x:expr ) 重复匹配多次
// => $x:expr 将expr匹配值绑定给变量x
// => 后面使用 $x 获取匹配值
( $( $x:expr ),* ) => {{
$(print!("{0}, ",$x);)*; // 让 $(temp_vec.push($x);) 重复匹配多次
println!("")
}};
}
fn main()
{
my_print!(1,2,3);
my_print!(1,2,3,4,5,6);
my_print!(1,2,3, "hello", "world", "worinima");
}
➜ main make
rustc main.rs
./main
1, 2, 3,
1, 2, 3, 4, 5, 6,
1, 2, 3, hello, world, worinima,
➜ main
2. 自定义宏指令的模式匹配
macro_rules! foo {
(x => $e:expr) => (println!("mode X: {}", $e));
(y => $e:expr) => (println!("mode Y: {}", $e));
}
/**
macro_rules! foo {
匹配规则 => {{ ...匹配中之后执行的语句... }};
(x => $e:expr) => {{println!("mode X: {}", $e)}};
(y => $e:expr) => {{println!("mode Y: {}", $e)}};
}
*/
fn main() {
foo!(x => 3);
foo!(y => 4);
foo!(y => 5);
// foo!(z => 6); // error
}
➜ main make
rustc main.rs
./main
mode X: 3
mode Y: 4
mode Y: 5
➜ main
4. 示例1
// 宏定义
macro_rules! my_vec {
( $( $x:expr ),* ) => {{
let mut temp_vec = Vec::new();
$(temp_vec.push($x);)*; // 让 $(temp_vec.push($x);) 重复匹配多次
temp_vec
}};
}
fn main()
{
// 通过语句创建Vec对象
{
let x: Vec = {
let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
};
println!("x = {:?}", x);
}
// 宏定义替换如上创建Vec的所有代码
{
let y = my_vec!(1,2,3); // => $(temp_vec.push($x);)* 匹配
println!("y = {:?}", y);
}
}
➜ main make
rustc main.rs
./main
x = [1, 2, 3]
y = [1, 2, 3]
➜ main
5. 示例2:递归解析HTML
macro_rules! write_html {
// 匹配1(递归结束分支)
($w:expr, ) => (());
// 匹配2
($w:expr, $e:tt) => {{
println!("2 => $w = {}, $e = {}", $w, $e);
write!($w, "{}", $e)
}};
// 匹配3
($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)* ) => {{
println!("3.1 => $w = {}, stringify!($tag) = {}", $w, stringify!($tag));
write!($w, "<{}>", stringify!($tag));
write_html!($w, $($inner)*);
println!("3.2 => $w = {}, stringify!($tag) = {}", $w, stringify!($tag));
write!($w, "{}>", stringify!($tag));
write_html!($w, $($rest)*);
}};
}
fn main() {
use std::fmt::Write;
let mut out = String::new();
write_html!(
&mut out,
html[head[title["Main Title"]]body[h1["H1 Sub Title"]]]
);
println!("out = {:?}", out);
}
➜ main make
rustc main.rs
3.1 => $w = , stringify!($tag) = html
3.1 => $w = , stringify!($tag) = head
3.1 => $w = , stringify!($tag) = title
2 => $w = , $e = Main Title
3.2 => $w = Main Title, stringify!($tag) = title
3.2 => $w = Main Title , stringify!($tag) = head
3.1 => $w = Main Title , stringify!($tag) = body
3.1 => $w = Main Title , stringify!($tag) = h1
2 => $w = Main Title , $e = H1 Sub Title
3.2 => $w = Main Title H1 Sub Title, stringify!($tag) = h1
3.2 => $w = Main Title H1 Sub Title
, stringify!($tag) = body
3.2 => $w = Main Title H1 Sub Title
, stringify!($tag) = html
out = "Main Title H1 Sub Title
"
➜ main
在一个匹配器中,每个元变量都有一个“片段说明符”,来识别匹配哪些语法形式。
- ident:标识符。例如:
x; foo
。 - path:一个合格的名字。例如:
T::SpecialA
。 - expr: 一个表达式。例如:
2 + 2; if true then { 1 } else { 2 }; f(42)
。 - ty:一个类型。例如:
i32; Vec<(char, String)>; &T
。 - pat:一个模式。例如:
Some(t); (17, 'a'); _
。 - stmt:单个语句。例如:
let x = 3
。 - block:一个括号分隔的语句序列。例如:
{ log(error, "hi"); return 12; }
。 - item:一个项目。例如:
fn foo() { }; struct Bar;
。 - meta:一个 "元项目", 在属性中建立的。 例如:
cfg(target_os = "windows")
。 - tt:一个单个标记树。
6. 常见的宏
1. panic!
panic!("oh no!");
2. vec!
let v = vec![1, 2, 3, 4, 5];
let v = vec![0; 100];
3. assert! 和 assert_eq!
// A-ok!
assert!(true);
assert_eq!(5, 3 + 2);
// nope :(
assert!(5 < 3);
assert_eq!(5, 3);
4. try!
use std::fs::File;
fn foo() -> std::io::Result<()> {
let f = try!(File::create("foo.txt"));
Ok(())
}