let file: Box<Read> = match fname {
"-" => Box::new(stdin.lock()),
_ => Box::new(fs::File::open(fname).unwrap_or_else(|err| {
writeln!(io::stderr(), "{}: \"{}\"", err, fname).unwrap();
process::exit(1);
}))
};
Type Result has its very own set of control flow primitives.[1] So does type Option.[2] Any type can have its very own flow control primitives. Are we going to see date.if_weekday(|day| { ... })
and similar cruft for every type? I hope not.Hopefully the setup of closures that probably won't be executed isnt't too expensive. Do those require a heap allocation and release when not used, or is this all on the stack? The run time variation for small changes indicates that some constructs are more expensive than others, but it's hard to know which ones are bad.
I understand the rationale behind the Rust approach to error handling, but it's just painful to look at. After seeing the gyrations people go through in Go and Rust to deal with the lack of exceptions, it looks like leaving exceptions does not make a language simpler. From a compiler perspective, the compiler can generally assume that exceptions are the rare case, and can optimize accordingly. Rust has no idea which closure a function will call, if any.
[1] https://doc.rust-lang.org/std/result/enum.Result.html [2] https://doc.rust-lang.org/std/option/enum.Option.html