即使未执行,变量也会被移至闭包
Variable is moved to closure even when it is not executed
我有一个函数可以 return 只有一个错误,所以我想创建一次,如果需要的话 return 该实例。
这里有一个例子来演示:
fn foo() -> Result<(), String> {
let err = String::from("error message");
let a = function_that_returns_an_option().ok_or_else(|| err)?;
let b = function_that_returns_another_option().ok_or_else(|| err)?;
// ...do something with a and b...
Ok(())
}
这会导致以下编译错误:
error[E0382]: use of moved value: `err`
--> src/main.rs:12:61
|
10 | let err = String::from("error message");
| --- move occurs because `err` has type `String`, which does not implement the `Copy` trait
11 | let a = function_that_returns_an_option().ok_or_else(|| err)?;
| -- --- variable moved due to use in closure
| |
| value moved into closure here
12 | let b = function_that_returns_another_option().ok_or_else(|| err)?;
| ^^ --- use occurs due to use in closure
| |
| value used here after move
我以为移动是懒惰发生的,但如果我理解正确,err
被移动到第一个闭包,即使闭包没有执行,因此它不能在第二个闭包(或编译器)中使用不知道并拒绝它只是为了安全?)。我可以用 err.clone()
替换闭包中的 err
,但这有点违背了目的。是否有另一种更“惯用”的方式来做到这一点?
要拥有一个可以以“动态检查”方式移出的变量,您可以将值包装在 Option
中并使用 Option::take
:
let mut err = Some(String::from("error message"));
let a = function_that_returns_an_option().ok_or_else(|| err.take().unwrap())?;
let b = function_that_returns_another_option().ok_or_else(|| err.take().unwrap())?;
(需要 .unwrap()
,因为 .take()
returns Option<String>
,因为该值可能已被占用。)
但是,无论如何,这不是错误处理的最佳选择,因为即使函数成功,您也会分配错误字符串。有一种直接的方法可以避免这种情况并进一步简化代码:将分配放在闭包中,并重用闭包而不是消息值:
let err = || String::from("error message");
let a = function_that_returns_an_option().ok_or_else(err)?;
let b = function_that_returns_another_option().ok_or_else(err)?;
我有一个函数可以 return 只有一个错误,所以我想创建一次,如果需要的话 return 该实例。
这里有一个例子来演示:
fn foo() -> Result<(), String> {
let err = String::from("error message");
let a = function_that_returns_an_option().ok_or_else(|| err)?;
let b = function_that_returns_another_option().ok_or_else(|| err)?;
// ...do something with a and b...
Ok(())
}
这会导致以下编译错误:
error[E0382]: use of moved value: `err`
--> src/main.rs:12:61
|
10 | let err = String::from("error message");
| --- move occurs because `err` has type `String`, which does not implement the `Copy` trait
11 | let a = function_that_returns_an_option().ok_or_else(|| err)?;
| -- --- variable moved due to use in closure
| |
| value moved into closure here
12 | let b = function_that_returns_another_option().ok_or_else(|| err)?;
| ^^ --- use occurs due to use in closure
| |
| value used here after move
我以为移动是懒惰发生的,但如果我理解正确,err
被移动到第一个闭包,即使闭包没有执行,因此它不能在第二个闭包(或编译器)中使用不知道并拒绝它只是为了安全?)。我可以用 err.clone()
替换闭包中的 err
,但这有点违背了目的。是否有另一种更“惯用”的方式来做到这一点?
要拥有一个可以以“动态检查”方式移出的变量,您可以将值包装在 Option
中并使用 Option::take
:
let mut err = Some(String::from("error message"));
let a = function_that_returns_an_option().ok_or_else(|| err.take().unwrap())?;
let b = function_that_returns_another_option().ok_or_else(|| err.take().unwrap())?;
(需要 .unwrap()
,因为 .take()
returns Option<String>
,因为该值可能已被占用。)
但是,无论如何,这不是错误处理的最佳选择,因为即使函数成功,您也会分配错误字符串。有一种直接的方法可以避免这种情况并进一步简化代码:将分配放在闭包中,并重用闭包而不是消息值:
let err = || String::from("error message");
let a = function_that_returns_an_option().ok_or_else(err)?;
let b = function_that_returns_another_option().ok_or_else(err)?;