为何Rust中parse()仅在包含断言时才能推断返回类型?
Rust filter_map中parse的类型推断问题解答
核心问题1:有断言时parse为何能推断类型?推断的类型是什么?
当保留断言代码时,assert_eq!(iter.next(), Some(1))里的1是Rust默认的i32类型,编译器会顺着这个线索反推:
iter.next()返回的是Option<T>,要和Some(1)匹配,所以T必须是i32;filter_map闭包的返回值就是这个Option<T>,而它来自s.parse().ok()——ok()是Result<T, E>的方法,作用是把成功的Ok(T)转成Some(T),失败的Err(E)转成None;- 因此编译器能确定:
s.parse()必须返回Result<i32, ParseIntError>(其中ParseIntError是i32实现FromStrtrait时对应的错误类型)。
简单来说,断言里的具体数值给了编译器明确的类型锚点,让它知道parse要解析成i32。
核心问题2:注释掉断言后为什么推断失败?
没有断言的话,代码里没有任何地方约束T的具体类型——filter_map生成的迭代器类型是FilterMap<..., ...>,其中的泛型参数T没有被后续代码使用,编译器无法判断你要把字符串解析成i32、u32还是其他实现了FromStr的类型,自然会报类型不明确的错误。
如何手动指定parse的类型?
你之前的写法有误,正确的方式是用turbofish语法(<T>)给parse方法指定目标类型,而不是直接写Result的类型:
let a = ["1", "two", "NaN", "four", "5"]; // 用::<i32>明确指定parse的目标类型 let mut iter = a.iter().filter_map(|s| s.parse::<i32>().ok());
这样不管有没有断言,编译器都能确定parse返回Result<i32, ParseIntError>,ok()转成Option<i32>,迭代器就能正常工作。
补充说明:FromStr是目标类型T需要实现的trait,不是Result实现的——parse方法的定义是fn parse<T: FromStr>(&self) -> Result<T, T::Err>,只要T实现了FromStr,就能调用parse解析成该类型。
内容的提问来源于stack exchange,提问作者Muhammad Qasim
相关产品推荐
相关产品推荐

