该Option::and_then函数允许简化此代码:
let foo = Some(1);
let bar = match foo {
Some(i) => Some(i + 1),
None => None,
};
println!("Foo: {:?}", foo);
Run Code Online (Sandbox Code Playgroud)
进入这个:
let foo = Some(1);
let bar = foo.and_then(|i| Some(i + 1));
println!("Foo: {:?}", foo);
Run Code Online (Sandbox Code Playgroud)
如果我用Strings 尝试相同的东西,它不会编译:
let foo = Some("bla".to_string());
let bar = foo.and_then(|ref f| Some(f.clone()));
println!("Foo: {:?}", foo);
Run Code Online (Sandbox Code Playgroud)
error[E0382]: use of moved value: `foo`
--> src/main.rs:4:27
|
3 | let bar = foo.and_then(|ref f| Some(f.clone()));
| --- value moved here
4 | println!("Foo: {:?}", foo);
| ^^^ value used here after move
|
= note: move occurs because `foo` has type `std::option::Option<std::string::String>`, which does not implement the `Copy` trait
Run Code Online (Sandbox Code Playgroud)
但是,相应的match表达式有效:
let foo = Some("bla".to_string());
let bar = match foo {
Some(ref f) => Some(f.clone()),
None => None,
};
println!("Foo: {:?}", foo);
Run Code Online (Sandbox Code Playgroud)
有没有办法缩短这个匹配表达式,就像我的第一个带整数的例子一样?
在这个最小的例子中,我本来可以使用map,但在我的真实代码中,我正在调用另一个返回一个Option我真正需要的函数and_then.只是我不想用一个不影响问题的额外函数来复杂化这个例子.
我真的需要foo事后使用,否则就不会有任何问题(实际上,foo我需要多次使用一个闭包捕获,而Man!我很难找到为什么编译器一直拒绝我的代码!错误the trait FnMut... is not implemented for the type [closure@...]没有给出很多指示,为什么它不是).
我clone在示例中使用了因为我想要使用字符串进行简单的操作.在真正的代码中,foo不是一个字符串(它是一个Regex),我不是在闭包中克隆它(我将它应用于字符串并处理结果).此外,此代码将被多次调用,因此避免不必要的分配和复制很重要.
Luk*_*odt 13
首先:您实际想要使用的方法是map在这里,因为您只想更改内部值.and_then如果Option在闭包中创建另一个,则非常有用.
回答你的问题:你不能再访问是正确的foo.如果你看一下函数声明......
fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U>
// ^^^^
Run Code Online (Sandbox Code Playgroud)
......你看到第一个论点是self.这意味着该方法消耗self(获取所有权),因此foo被移入方法并且不能再使用.
如果您bar之后只需要(通常是这种情况),您应该打印bar.如果你真的需要foo,你也可以这样做:
let bar = foo.as_ref().map(|s| s.clone());
Run Code Online (Sandbox Code Playgroud)
as_ref创建一个Option只包含对原始内部变量的引用的new .引用是Copy类型,因此Option可以安全地使用map.
你想使用Option::as_ref:
fn main() {
let foo = Some("bla".to_string());
let bar = foo.as_ref().and_then(|f| Some(f.clone()));
println!("Foo: {:?}", foo);
}
Run Code Online (Sandbox Code Playgroud)