如何从Rust中的迭代器解包BTreeMap项元组?

时间:2016-06-06 13:31:36

标签: dictionary rust

Here是示例代码:

use std::collections::BTreeMap;

fn main() {
    let mut map: BTreeMap<u8, Vec<u8>> = BTreeMap::new();
    let idx = map.iter_mut().find(|t| {
        let (&k, &mut v) = t;
        v.is_empty()
    });
    idx.map(|t| {
        let (&k, &mut v) = t;
        v.push(5);
    });
}

错误:

<anon>:6:13: 6:25 error: mismatched types:
 expected `&(&u8, &mut collections::vec::Vec<u8>)`,
    found `(_, _)`
(expected &-ptr,
    found tuple) [E0308]
<anon>:6         let (&k, &mut v) = t;
                     ^~~~~~~~~~~~

元组的类型是&(&u8, &mut collections::vec::Vec<u8>)所以我希望它可以通过以下方式解压缩:

let (&k, &mut v) = *t;

但是

<anon>:10:28: 10:30 error: type `(&u8, &mut collections::vec::Vec<u8>)` cannot be dereferenced
<anon>:10         let (&k, &mut v) = *t;
                                     ^~

如何解压缩并用于可变用途?

1 个答案:

答案 0 :(得分:3)

查看错误消息:

 expected `&(&u8, &mut collections::vec::Vec<u8>)`,
    found `(_, _)`
(expected &-ptr,
    found tuple) [E0308]

编译器期望与引用匹配,但代码不提供此类引用。将绑定更改为let &(&k, &mut v) = t。然后你会得到一堆其他错误:

  1. 使用&mut foo进行匹配意味着foo&mut剥离,然后结果值将移动到{{1 }}。这是因为它是一种模式匹配,就像foo“剥离”let Some(foo) = ...一样。

  2. 您无法移动Some,因为它归Vec所有,因此您需要参考它。这是通过BTreeMap关键字完成的,而不是ref运算符。

  3. 通常,你也会在闭包参数中直接进行模式匹配,而不是在第二个变量中进行模式匹配。

  4. 由于&会将项目的所有权转移到闭包,因此您只需提供map绑定,无需任何参考。

  5. 由于mut未使用,因此使用下划线(k)替换名称是惯用的。

  6. _
      

    用于可变用途

    如果你的意思是“如何将闭包中的值变为let idx = map.iter_mut().find(|&(k, ref v)| { v.is_empty() }); idx.map(|(_, mut v)| { v.push(5); }); ”,答案是“你不能”。 Find返回对迭代项(find)的不可变引用:

    &Self::Item

    即使你的fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool 可能是一个可变引用,对可变引用的不可变引用仍然是不可变的。