rust 为什么for_each不能替换代码中的for循环?

xe55xuns  于 2022-12-23  发布在  其他
关注(0)|答案(3)|浏览(291)

我的原始代码是:

const DNA: [char; 4] = ['A', 'C', 'G', 'T'];
...
let mut map: HashMap<char, usize> = HashMap::new();
/* initialize the hashmap */

for d in DNA.iter() {
    map.insert(*d, 0);
}

代码已经编译好了,然后我想用for_each替换for循环:

DNA.iter().for_each(|d| map.insert(*d, 0));

编译错误:

error[E0308]: mismatched types                                                                 
  --> src/lib.rs:26:29                                                                        
   |                                                                                          
26 |     DNA.iter().for_each(|d| map.insert(*d, 0));                                          
   |                             ^^^^^^^^^^^^^^^^^ expected `()`, found enum `Option`         
   |                                                                                          
   = note: expected unit type `()`                                                            
                   found enum `Option<usize>`

看起来for_each和for并不完全等价,为什么for_each不直接忽略map.insert()的返回值呢?

bogh5gae

bogh5gae1#

为什么for_each不直接忽略map.insert()的返回值呢?
因为Rust语法根本不是这样工作的。
1.每个函数都有一个返回类型,省略它并不意味着“没有返回值”,这是-> ()的语法糖,即返回类型为“unit”。
1.显式的return map.insert(*d, 0);和块末尾没有分号的简写map.insert(*d, 0)都是return语句,它们是显式的“在这里返回”,而不是可选的“如果有意义,可能返回一个值”。
因此,您当前尝试提供一个Option<V>,而函数签名需要一个(),这就是为什么会出现所示的错误。
因此,您必须调整闭包,使其不返回该值(或者更具体地说,返回单位类型()):

// the explicit version
DNA.iter().for_each(|d| {
  map.insert(*d, 0);
  ()
});
// the more idiomatic, shorter equivalent
DNA.iter().for_each(|d| { map.insert(*d, 0); });

注意第一个版本返回的值与函数签名匹配,第二个版本只是语法上的糖衣炮弹,可以省略返回值()

xcitsw88

xcitsw882#

其他的答案解释了问题是什么,以及解决方案是什么(使返回类型为()),但是,没有一个答案提到标准库中有一个函数,在序言中,这个函数就是这样做的:它是drop。实际上,drop: fn(T) -> ()是任何类型的T,它没有做任何其他事情(它的定义就是fn drop<T>(_: T) {})。
为了解决你的问题,你可以

DNS.iter().for_each(|d| drop(map.insert(*d, 0)))
qaxu7uf2

qaxu7uf23#

fn for_each<F>(self, f: F)where
    Self: Sized,
    F: FnMut(Self::Item)

以上是std::iter::for_each的函数签名。注意,约束F: FnMut(Self::Item)意味着它只能用回调函数调用,该回调函数以Self::Item作为输入,并且不返回任何值。如果您必须使用for_each执行此任务,则可以选择附加分号;,使闭包不返回任何值。尽管这与for ... in版本的标点符号数量几乎相同。

DNA.iter().for_each(|d| {
    map.insert(*d, 0);
});

rust eclipse 文件上的std::iter::for_each

相关问题