有没有办法在 Option 中拆分变量而不必使用 if 语句?
Is there a way to split up a variable inside an Option without having to use if statements?
我希望下面的代码能够工作,但是由于 map()
取得了 Option
的所有权,而且 Option
似乎没有 clone()
函数, 以下不编译。
fn main() {
struct ItemA {
a: String,
b: String,
}
let foo = Some(ItemA {
a: "A String".to_owned(),
b: "B String".to_owned(),
});
// OR
// let foo = None;
let opA: Option<String> = foo.map(|c| c.a);
let opB: Option<String> = foo.map(|c| c.b);
}
error[E0382]: use of moved value: `foo`
--> src/main.rs:15:31
|
14 | let opA: Option<String> = foo.map(|c| c.a);
| --- value moved here
15 | let opB: Option<String> = foo.map(|c| c.b);
| ^^^ value used here after move
|
= note: move occurs because `foo` has type `std::option::Option<main::ItemA>`, which does not implement the `Copy` trait
如果 opA
可以取得 ItemA.a
的所有权(这样就不必克隆字符串),并且 opB
可以取得 [=19] 的所有权,那就太好了=]
是否可以在不必使用 if 语句检查 Option
是 Some
还是 None
的情况下,展开并单独包装它。
您可以使用 map_or_else
.
let (opA, opB) = foo.map_or_else(
|| (None, None),
|c| (Some(c.a), Some(c.b))
);
如果 foo
是 None
,并且 returns 两个 None
,则调用第一个函数。如果 foo
为 Some
并将成员拆分为一个元组,则调用第二个函数。
当然,与简单的 match
相比,这并不能真正为您节省多少,而且可能更难理解。
let (opA, opB) = match foo {
None => (None, None),
Some(c) => (Some(c.a), Some(c.b))
};
顺便说一下,Option
确实实现了 Clone
,但它要求包含的类型实现 Clone
.
[T]here doesn't seem to be a clone()
function for Option
[...]
错了,there is,如果内部类型也实现了 clone
。所以在你的情况下,只需将 #[derive(Clone)]
添加到你的 struct ItemA
.
接下来可以使用as_ref
创建一个Option<&T>
然后使用map
.
let op_a = foo.as_ref().map(|c| &c.a);
let op_b = foo.as_ref().map(|c| &c.b);
println!("{:?}", op_a);
println!("{:?}", op_b);
我希望下面的代码能够工作,但是由于 map()
取得了 Option
的所有权,而且 Option
似乎没有 clone()
函数, 以下不编译。
fn main() {
struct ItemA {
a: String,
b: String,
}
let foo = Some(ItemA {
a: "A String".to_owned(),
b: "B String".to_owned(),
});
// OR
// let foo = None;
let opA: Option<String> = foo.map(|c| c.a);
let opB: Option<String> = foo.map(|c| c.b);
}
error[E0382]: use of moved value: `foo`
--> src/main.rs:15:31
|
14 | let opA: Option<String> = foo.map(|c| c.a);
| --- value moved here
15 | let opB: Option<String> = foo.map(|c| c.b);
| ^^^ value used here after move
|
= note: move occurs because `foo` has type `std::option::Option<main::ItemA>`, which does not implement the `Copy` trait
如果 opA
可以取得 ItemA.a
的所有权(这样就不必克隆字符串),并且 opB
可以取得 [=19] 的所有权,那就太好了=]
是否可以在不必使用 if 语句检查 Option
是 Some
还是 None
的情况下,展开并单独包装它。
您可以使用 map_or_else
.
let (opA, opB) = foo.map_or_else(
|| (None, None),
|c| (Some(c.a), Some(c.b))
);
如果 foo
是 None
,并且 returns 两个 None
,则调用第一个函数。如果 foo
为 Some
并将成员拆分为一个元组,则调用第二个函数。
当然,与简单的 match
相比,这并不能真正为您节省多少,而且可能更难理解。
let (opA, opB) = match foo {
None => (None, None),
Some(c) => (Some(c.a), Some(c.b))
};
顺便说一下,Option
确实实现了 Clone
,但它要求包含的类型实现 Clone
.
[T]here doesn't seem to be a
clone()
function forOption
[...]
错了,there is,如果内部类型也实现了 clone
。所以在你的情况下,只需将 #[derive(Clone)]
添加到你的 struct ItemA
.
接下来可以使用as_ref
创建一个Option<&T>
然后使用map
.
let op_a = foo.as_ref().map(|c| &c.a);
let op_b = foo.as_ref().map(|c| &c.b);
println!("{:?}", op_a);
println!("{:?}", op_b);