Option::and_then
函数可以简化以下代码:
let foo = Some(1);
let bar = match foo {
Some(i) => Some(i + 1),
None => None,
};
println!("Foo: {:?}", foo);
转化为这个:
let foo = Some(1);
let bar = foo.and_then(|i| Some(i + 1));
println!("Foo: {:?}", foo);
如果我用String
尝试相同的操作,它不会编译:
let foo = Some("bla".to_string());
let bar = foo.and_then(|ref f| Some(f.clone()));
println!("Foo: {:?}", foo);
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
然而,相应的match
表达式是有效的:
let foo = Some("bla".to_string());
let bar = match foo {
Some(ref f) => Some(f.clone()),
None => None,
};
println!("Foo: {:?}", foo);
有没有一种方法可以像我的第一个整数示例那样缩短此匹配表达式?
在这个最简示例中,我可以使用
map
,但在我真正的代码中,我正在调用另一个返回Option
的函数,所以我确实需要使用and_then
。只是我不想用一个额外的函数来复杂化没有影响到问题的示例。我真的需要在之后使用
foo
,否则就不会有任何问题(实际上,foo
被一个闭包所捕获,我需要多次使用它,而且我的天啊!我费了好大劲才找到为什么编译器一直拒绝我的代码!错误信息“the trait FnMut... is not implemented for the type [closure@...]”并没有给出太多关于为什么不行的提示)。我在示例中使用了
clone
,因为我想要一个使用字符串的简单操作。在真正的代码中,foo
不是一个字符串(而是一个Regex
),我没有在闭包中克隆它(我正在应用它到一个字符串上并处理结果)。此外,这段代码将被调用很多次,因此避免不必要的分配和复制非常重要。
as_ref
方法时相同数量的克隆结束了吗?也就是一个? - Benjamin Lindleyclone
只是一个例子,OP可能想将其更改为更有意义的内容。目前你的答案中的and_then
没有任何作用... :/ - Lukas Kalbertodtf +“one”
或字符串上的其他修改操作。无论哪种方式,你都需要在某个时候克隆该字符串。我只是提前做了这件事。 - Benjamin Lindley