Sas*_*ssa 3 fold rust rust-result
我正在使用正则表达式包来找到这个正则表达式的一些文本:
lazy_static! {
static ref FIND_STEPS_RE: Regex =
Regex::new(r"my regex").unwrap();
}
Run Code Online (Sandbox Code Playgroud)
我想找到所有可能的捕获并迭代它们:
FIND_STEPS_RE.captures_iter(script_slice)
Run Code Online (Sandbox Code Playgroud)
每个捕获的元素由2个值组成:操作和数字.例如,输出可以是:
[("+", "10"), ("-", "20"), ("*", "2")]
Run Code Online (Sandbox Code Playgroud)
我想迭代它,解析数字并应用操作.
我试过了:
let e = FIND_STEPS_RE.captures_iter(script_slice)
.fold(0, |sum, value| apply_decoding_step)?;
Run Code Online (Sandbox Code Playgroud)
在哪里apply_decoding_step
:
fn apply_decoding_step(sum: i32, capture: regex::Captures<>) -> Result<i32> {
let number = parse_number(&capture[2])?;
match &capture[1] {
"+" => Ok(s + number),
"-" => Ok(s - number),
"*" => Ok(s * number),
"/" => Ok(s / number),
_ => bail!("Unknown step operator"),
}
}
Run Code Online (Sandbox Code Playgroud)
但我得到了这个错误:
error[E0271]: type mismatch resolving `<fn(i32, regex::Captures<'_>) -> std::result::Result<i32, Error> {apply_decoding_step} as std::ops::FnOnce<(i32, regex::Captures<'_>)>>::Output == i32`
--> src/main.rs:122:10
|
122 | .fold(seed, apply_decoding_step);
| ^^^^ expected enum `std::result::Result`, found i32
|
= note: expected type `std::result::Result<i32, Error>`
found type `i32`
Run Code Online (Sandbox Code Playgroud)
我认为这是因为我正在尝试将a折叠Result
成a i32
,但由于我需要解析第二个捕获值并且还需要otherwise
我的情况,我match
该如何解决?
正如jupp0r所述,初始值必须与闭包的返回值具有相同的类型.
Iterator::fold
发生错误时,我建议在折叠中不做任何操作:
let result = x.iter().try_fold(0, |acc, &i| apply_decoding_step(acc, i));
Run Code Online (Sandbox Code Playgroud)
完成:
fn main() {
let x = [("+", "10"), ("-", "20"), ("*", "2")];
let result = x.iter().try_fold(0, |acc, &i| apply_decoding_step(acc, i));
println!("{:?}", result);
}
fn apply_decoding_step(sum: i32, capture: (&str, &str)) -> Result<i32, ()> {
let number: i32 = capture.1.parse().expect("nope");
match capture.0 {
"+" => Ok(sum + number),
"-" => Ok(sum - number),
"*" => Ok(sum * number),
"/" => Ok(sum / number),
_ => Err(()),
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个企业级解决方案.我认为这样做的主要好处是迭代会在第一次Iterator::try_fold
遇到迭代时结束,而不是在列表的其余部分旋转.次要的好处包括能够为每个部分编写非常细粒度的测试(从字符串解析,算术运算,累积等):
let result = x.iter().fold(Ok(0), |acc, &i| {
acc.and_then(|acc| apply_decoding_step(acc, i))
});
Run Code Online (Sandbox Code Playgroud)
仔细看看 的类型签名fold
:
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{ ... }
Run Code Online (Sandbox Code Playgroud)
init
必须与 的返回值具有相同的类型f
。这也是编译器在错误消息中告诉您的内容。你可以做
fn apply_decoding_step(sum: Result<i32>, capture: regex::Captures<>) -> Result<i32> {
match sum {
Err(_) => sum,
Ok(s) => {
let number = parse_number(&capture[2])?;
match &capture[1] {
"+" => Ok(s + number),
"-" => Ok(s - number),
"*" => Ok(s * number),
"/" => Ok(s / number),
_ => bail!("Unknown step operator"),
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后用Ok
种子调用它:
.fold(Ok(seed), apply_decoding_step);
Run Code Online (Sandbox Code Playgroud)
现在,如果发生任何失败,您fold
将返回一个Err
.