在 Rust 中是否有一种惯用的链接 Option 的方法?
Is there an idiomatic way of chaining Option in Rust?
当反序列化深层嵌套结构时(例如从 JSON),遍历多个 Option
类型并不少见。
例如:
let foo = Foo {
x: Some(Bar {
y: Some(Baz {
z: Some(42),
})
})
};
是否有一种惯用的方式链接 Option 以访问深层嵌套的值?
到目前为止我有以下内容,但在其他支持可选链接的语言中都没有 foo.x?.y?.z
简洁:
let z = foo.x.as_ref().and_then(|x| x.y.as_ref()).and_then(|y| y.z);
let z = foo.x.as_ref().and_then(|x| x.y.as_ref()?.z);
let z = (|| foo.x.as_ref()?.y.as_ref()?.z)();
看起来 try_block
功能可能很合适,但目前还不稳定。
let z = try { foo.x.as_ref()?.y.as_ref()?.z };
如您所说,try
块非常适合此。
与此同时,您可以利用 ?
在函数中工作的事实,将您的表达式包装在一个闭包中并调用它:
let z = (|| foo.x.as_ref()?.y.as_ref()?.z )();
你可以写一个简单的宏让它更漂亮一点:
macro_rules! tryit {
($($e: tt)+) => {
(|| { $($e)+ })()
}
}
与try
块基本相同:
let z = tryit! { foo.x.as_ref()?.y.as_ref()?.z };
如果您不喜欢立即调用的闭包,另一种选择是使用像 map_for
or mdo
这样的板条箱。 map_for
示例:
use map_for::option::FlatMap;
let z = map_for!{
x <- foo.x.as_ref();
y <- x.y.as_ref();
=> y.z }:
免责声明:我写了 map_for
crate。
当反序列化深层嵌套结构时(例如从 JSON),遍历多个 Option
类型并不少见。
例如:
let foo = Foo {
x: Some(Bar {
y: Some(Baz {
z: Some(42),
})
})
};
是否有一种惯用的方式链接 Option 以访问深层嵌套的值?
到目前为止我有以下内容,但在其他支持可选链接的语言中都没有 foo.x?.y?.z
简洁:
let z = foo.x.as_ref().and_then(|x| x.y.as_ref()).and_then(|y| y.z);
let z = foo.x.as_ref().and_then(|x| x.y.as_ref()?.z);
let z = (|| foo.x.as_ref()?.y.as_ref()?.z)();
看起来 try_block
功能可能很合适,但目前还不稳定。
let z = try { foo.x.as_ref()?.y.as_ref()?.z };
如您所说,try
块非常适合此。
与此同时,您可以利用 ?
在函数中工作的事实,将您的表达式包装在一个闭包中并调用它:
let z = (|| foo.x.as_ref()?.y.as_ref()?.z )();
你可以写一个简单的宏让它更漂亮一点:
macro_rules! tryit {
($($e: tt)+) => {
(|| { $($e)+ })()
}
}
与try
块基本相同:
let z = tryit! { foo.x.as_ref()?.y.as_ref()?.z };
如果您不喜欢立即调用的闭包,另一种选择是使用像 map_for
or mdo
这样的板条箱。 map_for
示例:
use map_for::option::FlatMap;
let z = map_for!{
x <- foo.x.as_ref();
y <- x.y.as_ref();
=> y.z }:
免责声明:我写了 map_for
crate。