在下面的简化示例中,编译器报告match语句的一个分支返回bool,而另一个返回().

use std::collections::{HashMap, HashSet};

fn main() {
    let available = HashMap::from_iter([(2, "b"), (3, "c"), (4, "d")]);
    let mut set = HashSet::new();
    
    for i in [1, 2, 3, 4, 5] {
        match available.get(&i) {
            Some(s) => set.insert(*s),
            None => ()
        }
    }
}

但是,这会导致错误:

error[E0308]: `match` arms have incompatible types
  --> src/main.rs:10:21
   |
8  | /         match available.get(&i) {
9  | |             Some(s) => set.insert(*s),
   | |                        -------------- this is found to be of type `bool`
10 | |             None => ()
   | |                     ^^ expected `bool`, found `()`
11 | |         }
   | |_________- `match` arms have incompatible types

我如何通知编译器Match语句应该返回(),而从insert返回的bool应该被忽略?

推荐答案

通常的方法是将手臂放在一个块中,并为其加上;,因为这会 suppress 表达式的结果:

use std::collections::{HashMap, HashSet};

fn main() {
    let available = HashMap::from_iter([(2, "b"), (3, "c"), (4, "d")]);
    let mut set = HashSet::new();
    
    for i in [1, 2, 3, 4, 5] {
        match available.get(&i) {
            Some(s) => {
                set.insert(*s);
            }
            None => (),
        }
    }
}

一种可能不太常见的替代方法是将值反馈给一个函数,将其"转换"为(),例如drop

use std::collections::{HashMap, HashSet};

fn main() {
    let available = HashMap::from_iter([(2, "b"), (3, "c"), (4, "d")]);
    let mut set = HashSet::new();
    
    for i in [1, 2, 3, 4, 5] {
        match available.get(&i) {
            Some(s) => drop(set.insert(*s)),
            None => (),
        }
    }
}

或者,您也可以完全忽略第二个分支:

use std::collections::{HashMap, HashSet};

fn main() {
    let available = HashMap::from_iter([(2, "b"), (3, "c"), (4, "d")]);
    let mut set = HashSet::new();
    
    for i in [1, 2, 3, 4, 5] {
        if let Some(s) = available.get(&i) {
            set.insert(*s);
        }
    }
}

或者使用更高阶的函数来处理这种副作用,虽然这不是最常见的,但它是一件事:

use std::collections::{HashMap, HashSet};

fn main() {
    let available = HashMap::from_iter([(2, "b"), (3, "c"), (4, "d")]);
    let mut set = HashSet::new();
    
    for i in [1, 2, 3, 4, 5] {
        available.get(&i).map(|&s| set.insert(s));
    }
}

Rust相关问答推荐

使用nom将任何空白、制表符、白线等序列替换为单个空白

在没有引用计数或互斥锁的情况下,可以从Rust回调函数内的封闭作用域访问变量吗?

Box::new()会从一个堆栈复制到另一个堆吗?

铁 rust 中的共享对象实现特征

自定义结果枚举如何支持`?`/`FromResidual`?

取得本地对象字段的所有权

不能在Rust中使用OpenGL绘制三角形

使用Rust WASM读取文件

Rust proc_macro 和 syn:解析空格

找不到 .has_func 或 .get_func 的 def

为什么 Rust 的临时值有时有参考性有时没有?

分配给下划线模式时会发生什么?

类型判断模式匹配panic

为什么我不能克隆可克隆构造函数的Vec?

如何获得对数组子集的工作可变引用?

当我在 struct 中存储异步函数时,为什么它需要生命周期

在 Rust 中返回对枚举变体的引用是个好主意吗?

Cargo:如何将整个目录或文件包含在功能标志中?

`if let` 只是另一种编写其他 `if` 语句的方式吗?

基于名称是否存在的条件编译