高阶函数中的 Rust 生命周期
Rust Lifetimes in Higher Order Functions
我有一个映射:HashMap<&str, Vec<&str>>
,我正在尝试创建一个反向查找映射HashMap<&str, &str>
,它从原始向量中的每个元素指向原始键。
例如如下图
{
"k": vec!["a", "b"]
}
会变成
{
"a": "k",
"b": "k",
}
当我这样做时,它工作得很好:
let substitutes: HashMap<&str, Vec<&str>> = vec![("a", vec!["b", "c"])].into_iter().collect();
// Below works fine
let mut reversed: HashMap<&str, &str> = HashMap::new();
for (&k, v) in substitutes.iter() {
for vv in v.iter() {
reversed.insert(vv, k);
}
}
但是,如果我尝试使用高阶函数执行此操作,则它不起作用:
// Below doesn't work
let reversed_2: HashMap<&str, &str> = substitutes
.iter()
.flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
.collect();
并给出以下错误:
error[E0373]: closure may outlive the current function, but it borrows `k`, which is owned by the current function
--> src/main.rs:18:42
|
18 | .flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
| ^^^^^ - `k` is borrowed here
| |
| may outlive borrowed value `k`
|
note: closure is returned here
--> src/main.rs:18:29
|
18 | .flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `k` (and any other referenced variables), use the `move` keyword
|
18 | .flat_map(|(&k, v)| v.iter().map(move |&vv| (vv, k)))
| ^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
考虑到 vv
在 flat_map
.
下的同一范围内,我正在努力思考 vv
可能会比 k
长寿
对于获取我的 HOF 方法失败原因的更多信息真的很有帮助。
在这种情况下,编译器帮助完全正确:您需要在内部闭包上添加 move
。
let reversed_2: HashMap<&str, &str> = substitutes
.iter()
.flat_map(|(&k, v)| v.iter().map(move |&vv| (vv, k)))
.collect();
当您创建一个使用来自周围作用域的变量的匿名函数时,内联函数(称为 closure)需要访问这些变量。默认情况下,它引用它们,使它们在封闭范围内可用。然而,在这种情况下,闭包引用了 k
和 returns 它,这意味着它可以逃脱封闭范围。
.flat_map(|(&k, v)| {
// k is only valid in this anonymous function
// a reference to k is returned out of map and also out of flat_map
// (Note: no move)
v.iter().map(|&vv| (vv, k))
// the anonymous function ends, all references to k need to have ended
})
// A reference to k has been returned, even though k's lifetime has ended
// Compiler error!
当您切换到 move
闭包时,您将拥有这些事物本身的所有权,而不是引用封闭环境中的事物。这让你 return k
而不是对 k
的引用,回避了这个问题。
.flat_map(|(&k, v)| {
// k is only valid in this anonymous function
// k is moved out of the enclosing function and into the inner function
// Because it owns k, it can return it
// (Note: uses move)
v.iter().map(move |&vv| (vv, k))
// k has been moved out of this environment, so its lifetime does not end here
})
// k has been returned and is still alive
我有一个映射:HashMap<&str, Vec<&str>>
,我正在尝试创建一个反向查找映射HashMap<&str, &str>
,它从原始向量中的每个元素指向原始键。
例如如下图
{
"k": vec!["a", "b"]
}
会变成
{
"a": "k",
"b": "k",
}
当我这样做时,它工作得很好:
let substitutes: HashMap<&str, Vec<&str>> = vec![("a", vec!["b", "c"])].into_iter().collect();
// Below works fine
let mut reversed: HashMap<&str, &str> = HashMap::new();
for (&k, v) in substitutes.iter() {
for vv in v.iter() {
reversed.insert(vv, k);
}
}
但是,如果我尝试使用高阶函数执行此操作,则它不起作用:
// Below doesn't work
let reversed_2: HashMap<&str, &str> = substitutes
.iter()
.flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
.collect();
并给出以下错误:
error[E0373]: closure may outlive the current function, but it borrows `k`, which is owned by the current function
--> src/main.rs:18:42
|
18 | .flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
| ^^^^^ - `k` is borrowed here
| |
| may outlive borrowed value `k`
|
note: closure is returned here
--> src/main.rs:18:29
|
18 | .flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `k` (and any other referenced variables), use the `move` keyword
|
18 | .flat_map(|(&k, v)| v.iter().map(move |&vv| (vv, k)))
| ^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
考虑到 vv
在 flat_map
.
vv
可能会比 k
长寿
对于获取我的 HOF 方法失败原因的更多信息真的很有帮助。
在这种情况下,编译器帮助完全正确:您需要在内部闭包上添加 move
。
let reversed_2: HashMap<&str, &str> = substitutes
.iter()
.flat_map(|(&k, v)| v.iter().map(move |&vv| (vv, k)))
.collect();
当您创建一个使用来自周围作用域的变量的匿名函数时,内联函数(称为 closure)需要访问这些变量。默认情况下,它引用它们,使它们在封闭范围内可用。然而,在这种情况下,闭包引用了 k
和 returns 它,这意味着它可以逃脱封闭范围。
.flat_map(|(&k, v)| {
// k is only valid in this anonymous function
// a reference to k is returned out of map and also out of flat_map
// (Note: no move)
v.iter().map(|&vv| (vv, k))
// the anonymous function ends, all references to k need to have ended
})
// A reference to k has been returned, even though k's lifetime has ended
// Compiler error!
当您切换到 move
闭包时,您将拥有这些事物本身的所有权,而不是引用封闭环境中的事物。这让你 return k
而不是对 k
的引用,回避了这个问题。
.flat_map(|(&k, v)| {
// k is only valid in this anonymous function
// k is moved out of the enclosing function and into the inner function
// Because it owns k, it can return it
// (Note: uses move)
v.iter().map(move |&vv| (vv, k))
// k has been moved out of this environment, so its lifetime does not end here
})
// k has been returned and is still alive