Lv777

Lv777

github
twitter
jike
playstation
xiaoyuzhou

控制流

Rust 里的控制流与其他语言没什么差异.

if#

if 的条件不带 (), 条件必须是 bool 类型.

if 是表达式,JS 三元表达式效果直接达成了:

let x = if true { 1 } else { 2 }

循环#

循环控制的 loop 以前没见过,是无限循环。通过 breakcontinue 控制终止和跳过,Rust 里 break 还能返回值. break,continue 以及循环标签仨概念在 JS 的 for 里也有,就是 ES6 用习惯了没怎么接触.

标准库 Rangefor 配合起来感觉有点意思。写 JS 循环就想过怎么没个控制循环次数的简洁方案,这下满足了.

match#

match 类似 JS 里的 switch, 有严格检查确保穷尽了所有可能性。与 [[数据类型 #枚举]] 配合可以匹配提取枚举成员包含的值.

let value = match some_value {
	Some(i) => i,
	None => 0
}

可以使用通配符 other (还以为 other 是个关键字) 或 _其他场景做处理,通配符按常理应该写在最后一个条件,否则会导致其后写的条件完全无效.

match some_num {
	1 => call(),
	3 => check(),
	other => println!("{}", other),
	// 也可以用 _ 不获取剩余情况的具体值
	// _ => (),
}

if let#

只需处理一种情况的场景,使用 if let 语法更简洁,但比 match 少了穷尽检查.

if let Some(value) = some_value {
	println!("{}", value);
}

? 运算符#

类似 JS 中的可选链, 可作用于 OptionResult 传播错误或 None 值。只能写在返回值兼容的函数体内,比如要对 Result 使用 ? 必须返回 Result. 有一点不同是对 Result 可以在函数体任何位置使用,这样做会提前中断并返回 Result::Err.

模式匹配#

模式 是 Rust 中用来匹配类型结构的语法。有点像 JS 的解构赋值, 理解起来有点反逻辑思路,但可使用的场景更多,控制流大部分都能用模式匹配.

let 语句可以模式匹配,= 左侧的模式匹配右侧表达式,match 分支里的 => 左侧模式匹配 match 关键字右侧表达式,if let 语句 = 左侧模式匹配右侧表达式.

let (x, y) = (1, 2);

match some_value {
	Some(4) | Some(5) => {},
	Some(x) => {},
	None => {}
}

if let 1..=3 = some_value {
} else if is_true{
} else {
}

// 解构结构体
let User { name: username, age } = user;

这么看 if let 有点像 if (模式匹配结果) 句型.

可反驳性#

如果表达式存在不能匹配模式的可能,则这个模式是可反驳的,比如 match 里的分支条件。反之为不可反驳的模式。也可以说穷尽所有可能性的情况下是不可反驳的. letfor 只接受不可反驳模式.

忽略模式中的值#

  1. 使用 _ 忽略单个值,可以在一个模式中重复使用;
  2. 使用 .. 忽略剩余值,但必须保证被忽略的部分没有歧义;

匹配守卫#

match 的分支条件后可以用 if 关键字添加守卫,即额外的匹配条件.

match some_value {
	Some(1) | Some(2) => {},
	Some(v) if v > 0 => {},
	Some(_) => {},
	_ => {}
}

添加的 if 作用于前面的整个模式,如果同时使用了 | 运算符指定了多个模式,if 前的优先级更高。以后八成会被这个坑到.

match x {
	// 这里无论 x 是几都不会匹配
	1 | 2 | 3 if false => {},
	_ => {}
}

如果希望同时获取变量并匹配模式,可以使用 @ 绑定.

match user {
	// 这里的 age 被用来匹配了, 后面的块中无法访问 age 值
	User { age: 1..=18, .. } => {},
	// 这样就可以用了
	User { age: user_age @ 20..=35, .. } => {}
}
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。