From a PR point of view, I find that spelling Ok(()) in functions which return Result<(),E> is actually a good thing. It reads as: “and if we get here, then everything has worked ok”, which helps reinforce the notion that errors have been thought about and treated, and helps distinguish Rust from the perceived problems of exception-based solutions. I for one, am proud of our glorious Ok(()).
My counter-proposal is to simply define
as an alias for Ok(()).
I also don’t see any of the proposals as a win for teaching Rust. For instance, consider a case where a bunch of Result<T,E> gets stored in a data structure instead of T values, ie where a non-monadic function like map() has been used instead of a monadic one. In this case, I think it is easier to make sense of this (failing) example than what you get with throws.
fn faillible_seventeen(i: u32) -> Result<u32, SomeErrorType> {
Ok(17)
}
fn main() {
let v = vec![1,2,3,4];
let vv = v.map(faillible_seventeen);
assert_eq!(vv, [17,17,17,17]); // This won't type-check.
println!(success)
}
With throws, the code looks like the following, and it is harder to grasp the situation with the spurious Ok() around each 17.
fn faillible_seventeen(i: u32) -> u32 throws SomeErrorType {
17
}
fn main() {
let v = vec![1,2,3,4];
let vv = v.map(faillible_seventeen);
assert_eq!(vv, [17,17,17,17]); // This won't type-check
println!(success)
}
In particular, the second version gives the false impression that the following is not possible:
fn main() {
let v = vec![1,2,3,4];
let vv = v.flat_map(faillible_seventeen); // We keep the successful seventeens
assert_eq!(vv, [17,17,17,17]);
println!(success)
}