我有这个简单的解析功能
Set-Content
一切正常,但是我想要这样的Option或Result返回类型:
use std::collections::BTreeMap;
fn parse_kv(data: &str) -> BTreeMap<String, String> {
data.split('&')
.map(|kv| kv.split('='))
.map(|mut kv| (kv.next().unwrap().into(), kv.next().unwrap().into()))
.collect()
}
#[test]
fn parse_kv_test() {
let result = parse_kv("test1=1&test2=2");
assert_eq!(result["test1"], "1");
assert_eq!(result["test2"], "2");
}
此实现:
fn parse_kv(data: &str) -> Option<BTreeMap<String, String>>
不幸的是,出现以下错误:
fn parse_kv(data: &str) -> Option<BTreeMap<String, String>> {
Some(data.split('&')
.map(|kv| kv.split('='))
.map(|mut kv| (kv.next()?.into(), kv.next()?.into()))
.collect())
}
是否可以在闭包内部使用error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/ecb_cut_paste.rs:23:24
|
23 | .map(|mut kv| (kv.next()?.into(), kv.next()?.into()))
| ^^^^^^^^^^ cannot use the `?` operator in a function that returns `(_, _)`
|
= help: the trait `std::ops::Try` is not implemented for `(_, _)`
= note: required by `std::ops::Try::from_error`
运算符从此类函数返回?
?如果没有,我该如何习惯性地处理这种情况?
答案 0 :(得分:5)
这里的问题是闭包本身是一个函数,因此使用?
将从闭包而不是外部函数返回。仍然可以使用它来按所需方式实现该功能,
use std::collections::BTreeMap;
fn parse_kv(data: &str) -> Option<BTreeMap<String, String>> {
data.split('&')
.map(|kv| kv.split('='))
.map(|mut kv| Some((kv.next()?.into(), kv.next()?.into())))
.collect()
}
#[test]
fn parse_kv_test() {
let result = parse_kv("test1=1&test2=2").unwrap();
assert_eq!(result["test1"], "1");
assert_eq!(result["test2"], "2");
let result2 = parse_kv("test1=1&test2");
assert_eq!(result2, None);
}
这里有两点需要注意:首先,第二个Some(...)
调用中的问号和map
意味着您有一个Option<(String, String)>
的迭代器-类型推断可将其用于你。
下一个要注意的地方是collect()
可以自动将Iterator<Option<T>>
转换为Option<Collection<T>>
(与Result
-relevant documentation here相同)。我添加了一个测试,证明这可行。
要注意的另一件事是,以这种方式使用collect
仍然允许发生短路。迭代器产生第一个None
后,collect
将立即返回None
,而不是继续处理每个元素。