I think you could do something like that (though I'm not sure I find it more readable, question of usage I suppose):
try!(open_file()
.and_then(|f| f.read_file())
.and_then(|f| f.write_file())
.and_then(|f| f.close_file()));
Anyway, I guess it's a matter of taste, but personally I am not a big fan of try/catch blocks and like the way it is in Rust. Yes, in some case it is a bit more verbose, but I prefer to see clearly which parts can file. Compare this (try/catch style):
try {
let x = f(g(h()));
do_stuff(x);
} catch (...) {...}
with this (current rust style):
let x = f(try!(g(h())));
try!(do_stuff(x));
The latter case is a bit more verbose, but at least you clearly see that if there is an error it is because either or g
or do_stuff
, whereas in the former case it could be any function called.
What I find frustrating with try!
is that when you want to use it in a function that does not return a (compatible) Result
, you have to somehow refactor your code (which in some case might actually be a good thing in the long run but anyway).
On the other hand I guess it would be possible to implement some kind of macro which would allow to make "inner try!s" "return" from this macro instead of the function. E.g:
fn main() { // doesn't return a Result!
let x = 42;
catch!(error: SomeError {
let y = try!(some_stuff(x));
println!(y);
} {
println!("oops: {}", error.description());
});
println!("this will get printed in any case");
}
which would translate to something like:
fn main() {
let x = 42;
let closure = move || -> Result(_, SomeError) {
let y = try!(some_stuff(x));
println!(y);
}
match closure() {
Ok(x) => x,
Err(error) => println!("ooops: {}", error.description());
}
println!("this will get printed in any case");
}
At leat, i'm not very well versed in macros (and am not even sure using a closure for that wouldn't cause borrowcheck issues), but I think it should be possible to implement that with a macro. Though honestly I just got this idea but writing it I'm quite dubious it would be useful.