我试图使这种转换(Option<Option<String>>到Option<Option<&str>>)成为可能,但在尝试了包括使用.map在内的许多方法后仍然失败。我知道转换是可能的,但是,如果没有嵌套的Option(即Option<String>到Option<&str>):只使用.as_deref()。使用.map(|inner| inner.as_deref())违反了所有权。
Option<Option<String>>
Option<Option<&str>>
.map
Option
Option<String>
Option<&str>
.as_deref()
.map(|inner| inner.as_deref())
pcww981p1#
使用普通的map违反所有权规则的原因是因为它需要self。您正在使用外部的Option,然后试图从内部借用一些东西,这是不起作用的。然而,这里有一个简单的方法,在map中使用as_ref,然后使用as_deref。as_ref将&Option<T>转换为Option<&T>,其中T是Option<String>,因此当您调用map时,您将获得&Option<String>,然后您可以安全地将其传递给as_deref。
map
self
as_ref
as_deref
&Option<T>
Option<&T>
T
&Option<String>
fn main() { let foo = Some(Some(String::from("abc"))); let bar: Option<Option<&str>> = foo.as_ref().map(|r| r.as_deref()); eprintln!("{:?}", bar); }
字符串
carvr3hs2#
当你发现自己将多个方法和闭包串在一起来使用Option、Result,甚至像hash_map::Entry这样的东西时,* 考虑 * 回到基础并使用match:
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, } }
字符串这样做的好处是,当阅读时,它的含义是显而易见的;它实际上做了什么是毫无疑问的。如果需要改变它来做一些稍微不同的事情,如何做是显而易见的。它并不总是更好的(这个特殊的例子是特别不优雅的所有重复),但(在我看来)它总是值得考虑的选择。
2条答案
按热度按时间pcww981p1#
使用普通的
map
违反所有权规则的原因是因为它需要self
。您正在使用外部的Option
,然后试图从内部借用一些东西,这是不起作用的。然而,这里有一个简单的方法,在
map
中使用as_ref
,然后使用as_deref
。as_ref
将&Option<T>
转换为Option<&T>
,其中T
是Option<String>
,因此当您调用map
时,您将获得&Option<String>
,然后您可以安全地将其传递给as_deref
。字符串
carvr3hs2#
当你发现自己将多个方法和闭包串在一起来使用
Option
、Result
,甚至像hash_map::Entry
这样的东西时,* 考虑 * 回到基础并使用match
:字符串
这样做的好处是,当阅读时,它的含义是显而易见的;它实际上做了什么是毫无疑问的。如果需要改变它来做一些稍微不同的事情,如何做是显而易见的。
它并不总是更好的(这个特殊的例子是特别不优雅的所有重复),但(在我看来)它总是值得考虑的选择。