Boost logo

Boost :

Subject: Re: [boost] [outcome] New proposed factory API as per review feedback
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-05-25 14:14:05


>> In fact, I am increasingly thinking that a consensus position could be
>> this type factory template:
>>
>> // What to default construct to
>> enum class default_to
>> {
>> none,
>> T,
>> EC,
>> E
>> };
>>
>> // How much empty state to implement
>> enum class emptiness
>> {
>> never, // imposes restrictions on T, EC, E
>> formal, // formal empty state
>> tolerant // empty state iff EC and E don't have nothrow move
>> construction
>> };
>>
>> // How narrow or wide the observers will be
>> enum class observers
>> {
>> narrow, // accessing not the current state = reinterpret_cast
>> wide, // default actions already described earlier this review
>> single_shot // you can observe state precisely once only
>> };
>>
>> // Replacement for basic_monad
>> template<
>> class T, // what .value() returns, or void
>> class EC, // what .error() returns, or void
>> class E, // what .exception() returns, or void
>> default_to default_to_config,
>> emptiness empty_config,
>> observers observers_config
>>> class outcome_impl;
>>
>> // Outcome as apparently desired by reviewers
>> template<class T> using outcome = outcome_impl<
>> T,
>> error_code_extended,
>> std::exception_ptr,
>> default_to::none, // default constructed instance =
>> reinterpret_cast uninitialised memory
>> emptiness::never, // Never possible to be empty, not ever
>> observers::narrow // reinterpret_cast all observers
>>> ;
>>
>> // Result as apparently desired by reviewers
>> template<class T> using result = outcome_impl<
>> T,
>> error_code_extended,
>> void, // there is still a .exception(), but it returns
>> void and is not usable
>> default_to::none, // default constructed instance =
>> reinterpret_cast uninitialised memory
>> emptiness::never, // Never possible to be empty, not ever
>> observers::narrow // reinterpret_cast all observers
>>> ;
>>
>> See what you think of the proposed API above. We supply a precanned
>> outcome<T> and result<T> template alias, but end users can template
>> alias any configuration they like.
>>
>
> I am geting some contradictory information here. Is the fact that
> outcome<T> is built of policies part of the API which you commit to support
> in subsequent releases? It was my impression that you never wanted this to
> be exposed to the users. Now, when you use name "API" it looks like you do
> want to expose the policies?

Outcome was always supposed to be a *family* of Either monad varieties
which had well defined interoperation semantics with one another. So the
original idea was that there was a clean progression from option<T>
right through to future<T> with a single common implementation, with a
common DO/TRY/AWAIT mechanism, a common monadic BIND and MAP mechanism
and so on.

However I am personally uncomfortable supporting code I don't use in my
own software, so after AFIO v1 was rejected, my personal need for such a
wide family of Either monads, and the monadic operations, went away,
including the promise/future specialisation. You thus got the Outcome
presented for review here today which had been reduced to just outcome,
result and option.

During this review there are clear disagreements about what form and
semantics a C++ Either monad should take. People aren't even sold on the
Expected proposal. I don't get that criticism, I think the Expected
proposal just fine, but there you go.

Outcome's CRTP policy based implementation is very flexible. All the
code to implement all the varieties of Either monad which someone has
asked for at least once in this review is already in Outcome. It would
be a bit of work, but not too awful, to replace the preprocessor
stamping out of hard coded prefabricated specialisations for outcome,
result, option and expected with a template based compile time assembly
of parts to provide all the varieties mentioned above. I count:

4 x 3 x 3 x 3 combinations = 108 Either monad varieties

You can't possibly hope to test all these in a test suite. It's another
reason why I didn't propose this design originally. But if it's what
people want, and it's not stupidly dangerous which this is not, I can
give the people what they want.

(BTW, originally Outcome *did* use a template based compile time
assembly of parts. I replaced it with a hard coded preprocessor
generated edition for lower compile time cost. But the old mechanism can
be restored, and that would eliminate most of the preprocessor template
based code generation which some have complained about. I personally
suspect the template based system will be not particularly easier for
casual reading)

So do I want to expose the policies? Not really. But I can see no
consensus opinion on the shape and form for Expected, let alone for
Outcome, will emerge. So I propose Outcome provides all one hundred and
eight varieties of Either monad, and let Boost keep its reputation for
overwhelming complexity.

We'll see which forms end up being used most by end users, and that
would be great information for Vicente and WG21 to have to hand during
standardisation.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk