如何处理Rust中嵌套.map()返回Some/None?解决E0308类型不匹配
解决Rust中嵌套Option导致的类型不匹配错误(E0308)
你的代码因嵌套调用map(),返回类型变为Option<Option<Box<DomainCoach>>>,但convert_player的coach参数要求Option<Box<DomainCoach>>,从而触发E0308类型不匹配错误。
原代码及错误信息
函数定义:
pub fn convert_player( id: String, created_at: OffsetDateTime, //... coach_id: Option<String>, coach: Option<Box<DomainCoach>>, ) -> Self {}
调用代码:
Player::convert_player( o.id.to_owned(), o.created_at, //... o.coach_id.as_ref().map(|id| { // o.coach_id can be None self.coach_hashmap .get(id) // this can be None .map(|_| Box::new(self.convert_coach(id))) }) )
错误信息:
error[E0308]: mismatched types | 259 | Player::convert_player( | -------------------------------- arguments to this function are incorrect ... 296 | / o.coach_id.as_ref().map(|id| { 297 | | .map(|_| Box::new(self.convert_coach(id))) 298 | | }), | |______________^ expected `Option<Box<Coach>>`, found `Option<Option<Box<...>>>` | = note: expected enum `Option<Box<_>>` found enum `Option<Option<Box<_>>>` note: associated function defined here | 355 | pub fn convert( | ^^^^^^^^^^^^^^^^^^^ ... 375 | convert_coach: Option<Box<Coach>>, | ---------------------------------------------------
修正方案
方案1:用and_then替代外层map
and_then会在当前Option有值时执行闭包,并直接返回闭包的Option结果,自动避免嵌套:
Player::convert_player( o.id.to_owned(), o.created_at, //... o.coach_id.as_ref().and_then(|id| { self.coach_hashmap .get(id) .map(|_| Box::new(self.convert_coach(id))) }) )
原理:and_then接收的闭包返回Option<T>,最终整体返回Option<T>,完全匹配参数类型要求。
方案2:用flatten()展平嵌套Option
如果保留外层map,可以在最后调用flatten()将嵌套的Option一层展平:
Player::convert_player( o.id.to_owned(), o.created_at, //... o.coach_id.as_ref().map(|id| { self.coach_hashmap .get(id) .map(|_| Box::new(self.convert_coach(id))) }).flatten() )
原理:flatten()会把Option<Option<T>>转换为Option<T>,任意一层为None时,最终结果都是None。
方案3:用match手动处理空值
如果需要更清晰的分支逻辑,直接用match枚举所有情况:
Player::convert_player( o.id.to_owned(), o.created_at, //... match o.coach_id.as_ref() { Some(id) => self.coach_hashmap.get(id).map(|_| Box::new(self.convert_coach(id))), None => None, } )
原理:直接对coach_id的空值情况做分支处理,返回结果天然是Option<Box<DomainCoach>>,不会产生嵌套。
内容的提问来源于stack exchange,提问作者Fred Hors
相关产品推荐
相关产品推荐

