Skip to content
Snippets Groups Projects
Commit bfb377f0 authored by Per Lindgren's avatar Per Lindgren
Browse files

fallible iterator, with and without errors

parent bcc2b5a4
No related branches found
No related tags found
No related merge requests found
......@@ -76,27 +76,45 @@ fn type_check2(stmts: &Stmts) -> Result<Id, Error> {
// IMHO Result::map should have been named map_ok, since that is what is does, and symmetric to map_err.
fn type_check3(stmts: &Stmts) -> Result<Id, Error> {
let res =
stmts
.iter()
.try_fold::<_, _, Result<Id, Error>>("".to_string(), |_, stmt| match stmt {
Stmt::Let(id, _) => {
println!("let {} ...", id);
id.to_string();
Ok(id.to_string())
}
Stmt::If(_, _, __) => {
println!("if has an error");
Err(format!("error found in statement {:?}", stmt))
}
});
let res = stmts.iter().try_fold("".to_string(), |_, stmt| match stmt {
Stmt::Let(id, _) => {
println!("let {} ...", id);
Ok(id.to_string())
}
Stmt::If(_, _, __) => {
println!("if has an error");
Err(format!("error found in statement {:?}", stmt))
}
});
println!("here we can do something before returning");
res
}
// this is quite good, we can get rid of some book keeping, and we iterate only up to the point where an error occurs.
// we have to convert the Ok(()) into the last Id (using Result::map)
// IMHO Result::map should have been named map_ok, since that is what is does, and symmetric to map_err.
// this is likely as good as it gets using Rust.
// the `try_fold`, aborts on an error directly.
// we need to give an initial value for the accumulator ("".to_string())
// in this case we don't accumulate, so the first closure parameter is discarded (`_`)
// instead we just overwrite the accumatore with the latest seen identifier.
fn type_check4(stmts: &Stmts) -> Result<Id, Error> {
let res = stmts
.iter()
.try_fold("".to_string(), |_, stmt| match stmt {
Stmt::Let(id, _) => {
println!("let {} ...", id);
Ok(id.to_string())
}
Stmt::If(_, _, __) => {
println!("if has an error");
Err(format!("error found in statement {:?}", stmt))
}
})?;
println!("here we can do something before returning");
Ok(res)
}
// A slight alternation av type_check3, here we make an early return
// Notice that the type of `res` has changed.
#[test]
fn test_stmts() {
......@@ -108,5 +126,19 @@ fn test_stmts() {
];
println!("type_check {:?}", type_check(&stmts));
println!("type_check2 {:?}", type_check2(&stmts));
println!("type_check3 {:?}", type_check2(&stmts));
println!("type_check3 {:?}", type_check3(&stmts));
println!("type_check4 {:?}", type_check4(&stmts));
}
#[test]
fn test_stmts_without_error() {
let stmts = vec![
Stmt::Let("a".to_string(), NumOrId::Num(1)),
Stmt::Let("b".to_string(), NumOrId::Num(2)),
Stmt::Let("c".to_string(), NumOrId::Num(3)),
];
println!("type_check {:?}", type_check(&stmts));
println!("type_check2 {:?}", type_check2(&stmts));
println!("type_check3 {:?}", type_check3(&stmts));
println!("type_check4 {:?}", type_check4(&stmts));
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment