|
Boost : |
Subject: Re: [boost] [review] Review of Outcome v2 (Fri-19-Jan to Sun-28-Jan, 2018)
From: VinÃcius dos Santos Oliveira (vini.ipsmaker_at_[hidden])
Date: 2018-01-27 13:33:38
2018-01-27 0:31 GMT-03:00 Emil Dotchevski via Boost <boost_at_[hidden]>:
> 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/
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk