
2018-01-27 0:31 GMT-03:00 Emil Dotchevski via Boost
Question: if using the OUTCOME_TRY macro is equivalent to calling the function, checking for error and then returning an error if there is an error, how is this different from using exceptions? Semantically, exception handling does nothing more than check for errors and returning errors if there were errors
There is a single control flow to analyse: the return of the function. You don't need a "parallel" control flow construct to check for error case. This simplification just adds up: - You can't forget to check the error case (it's part of the type system). - It's self-documenting. - There are no strange interactions between Outcome and the rest of the language (e.g. throwing destructors, transporting exception between threads, and so on...). - Add templates to the mix and you'll remember who is responsible for non-insignificant amount of rules and added code boilerplate. - ... OUTCOME_TRY is just convenience. It mirrors the Rust's try macro: https://doc.rust-lang.org/1.9.0/std/macro.try!.html Rust has sum types and pattern matching at language level from day 0 (day 0 is Rust 1.0). The rest of the features were thought (or revised) with pattern matching in mind before 1.0 release. It has conveniences that C++ will never have (Rust /lacks/ constructors that can throw, moves that can throw and moved objects that will call a destructor). Rust doesn't have exceptions and nobody misses them. On the level of what C++ could have, Rust has monadic operations. with much more readable syntax:
return parse(read_data(open_file(path)));
Check OUTCOME_TRYX Of course it'd be more verbose: return parse(OUTCOME_TRYX(read_data(OUTCOME_TRYX(open_file(path))))); To the point of being ridiculous. Here it'd be better to split it in one line per call. In Rust, try! macro is only 4 letters long. Also, it was "promoted" to an operator: https://m4rw3r.github.io/rust-questionmark-operator With monadic operations, we could turn the above code into something like: return open_file(path).and_then(read_data).and_then(parse); But this assumes all operations return the same error type (e.g. std::error_code). This should be true at least to the I/O functions (open_file and read_data). Maybe we could use something like std::common_type or another magic detection to relax the requirements (i.e. it must be the same error type) a bit (it'd diverge from other implementations, but we have this freedom). -- VinÃcius dos Santos Oliveira https://vinipsmaker.github.io/