Boost logo

Boost :

Subject: Re: [boost] Boost.Outcome review - First questions
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2017-05-25 12:41:38

Thanks Vicente,

> >> There is still this case where you want to avoid exceptions in one part
> of
> >> the program, but still use exceptions in other parts of the program.
> For
> >> one example. in one "task" you launch another task with a callback
> >> function `f`. You might want to throw from `f` and this is valid. But
> the
> >> framework for launching tasks cannot afford to spill exceptions, so
> they
> >> have to catch and somehow transport the exception (e.g., by
> exception_ptr)
> >> then in the other task, you might want to re-convert to an exception.
> >> (something similar to what std::future does.)
> > I understand what you're saying, std::future needs a (conceptual)
> variant<T, exception_ptr> to store its state. So if I hear you correctly,
> outcome::expected<T, exception_ptr> could be used for that.
> I believe that yes, the underlying type of a future is an
> expected<T,exception_ptr>.
> Once the future is ready it has an expected in. I believe that we could
> even have it at the interface level. For me the future::then function
> should have a expected<T,exception_ptr> parameter, as this is the value
> you can find when the callback is called.
> But one thing at a time. First we need expected in the standard.

Nod, I tend to agree with this. Even if calling the continuation with a
variant<T, E> would give us the same semantics, especially with the monadic
helper functions you mention below.

> >> Also, maybe you will find of use the following example that tries to
> >> illustrate the basic use case of the library:
> > <snipped code example>
> >
> > Thanks, I think I've seen this in the docs. All of this could have been
> done with a variant<T, some_error_type> without changing the semantics,
> yes?
> With the code it will be easier to answer :) Sorry, I was unable to find
> it.
> If we had some PossibleValued, MonadError interfaces, variant<T, error>
> could be enough. As most of us we know Either T E is a Monad Error once
> we do the mapping. But we don't have them yet (at least not in the
> standard.

Yes, I'd rather have those monadic functions which could generically work
with any conceptually matching type than a special expected<> which mostly
duplicates functionality provided by another (already existing!) fundamental
type (variant<>)

> > So I guess the next question I would like to ask is: what is the benefit
> of using outcome::result<T> over std::optional<T>, and
> outcome::expected<T, E> over std::variant<T, E>?
> >
> Can I try to answer what are the benefits of using std::optional<T>
> instead of variant<nullopt_t,T>?
> The same answer should apply to your last question, isn't it?

Even if variant<nullopt_t, T> may be semantically somewhat equivalent to an
optional<T>, the mere fact that you have to deal with nullopt_t makes the
former awkward to use. In the case of variant<T, E>/expected<T, E> no
additional awkwardness arises (AFAICS), especially if we had those generic
monadic functions.

The only effect from introducing expected<> over variant<> + monadic
functions would be a nice bulk of near duplication of code. If we had those
(functions), then a simple using expected<T, E> = variant<T, E>; would do
the trick to even get the same syntax.

Regards Hartmut

Boost list run by bdawes at, gregod at, cpdaniel at, john at