我试图使这种转换Option<Option<String>>成为Option<Option<&str>>可能,但在尝试了许多方法(包括使用.map.
我知道转换是可能的,但是,如果没有嵌套Option(即Option<String>到Option<&str>):只需使用.as_deref().
使用.map(|inner| inner.as_deref())侵犯了所有权。
使用 plain 违反所有权规则的原因map是因为它需要self. 你正在消耗外部Option,然后试图从内部借用一些东西,这是行不通的。
然而,这里有一个简单的方法,使用as_ref然后as_deref在map. as_ref变成&Option<T>, Option<&T>where Tis Option<String>,因此当您调用时map,您会得到一个&Option<String>,然后您可以安全地传递给它as_deref。
fn main() {
let foo = Some(Some(String::from("abc")));
let bar: Option<Option<&str>> = foo.as_ref().map(|r| r.as_deref());
eprintln!("{:?}", bar);
}
Run Code Online (Sandbox Code Playgroud)
当您发现自己将多个方法和闭包串在一起以使用Option、Result,甚至类似的东西时hash_map::Entry,请考虑回到基础知识并使用match:
pub fn opt_opt_str_ref(input: &Option<Option<String>>) -> Option<Option<&str>> {
match input {
Some(Some(s)) => Some(Some(s.as_str())),
Some(None) => Some(None),
None => None,
}
}
Run Code Online (Sandbox Code Playgroud)
这样做的好处是读起来意思很明显;它的实际作用是毫无疑问的。如果需要对其进行更改以执行稍微不同的操作,那么如何操作是显而易见的。
它并不总是更好(这个特定的例子在所有重复中特别不雅),但(在我看来)它总是值得考虑的选择。