[review] **NEXT WEEK** Review of Outcome (starts Fri-19-May)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
107 messages Options
123456
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] **NEXT WEEK** Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list


> -----Original Message-----
> From: Boost [mailto:[hidden email]] On Behalf Of Andrzej Krzemienski via Boost
> Sent: 15 May 2017 13:26
> To: [hidden email]
> Cc: Andrzej Krzemienski
> Subject: Re: [boost] [review] **NEXT WEEK** Review of Outcome (starts Fri-19-May)
>
> 2017-05-15 13:08 GMT+02:00 Niall Douglas via Boost <[hidden email]>:
>
> >
> > >> you get a C++ exception thrown of type monad_error(no_state).
> > >
> > > As a side note, it would be nice from my point of view if you eradicate
> > > these last remaining references to 'monad' in the public interface and
> > > make that outcome_error (resp. outcome_errc, outcome_category.)
> >
> > A lot of people grumble at having "monad" in the naming. I don't
> > personally see the problem, it's just a name, and "basic_monad" is
> > exactly what is it: a building block for a monad.
> >
> > I'll tell you what though, if two more people strongly feel that
> > "basic_monad" and "monad_error" need to be renamed, I will do it. Please
> > people do suggest a better alternative name though.
> >
>
> I strongly feel that name "monad" need to be renamed :)
> Proposed alternatives:
>
>    - `basic_monad` -> `outcome_base` or `basic_outcome`
>    - `monad_error` -> `bad_outcome` or `outcome_error`

+1

monad == FUD :-(

basic_monad --> basic_outcome

monad_error --> bad_outcome

Paul

---
Paul A. Bristow
Prizet Farmhouse
Kendal UK LA8 8AB
+44 (0) 1539 561830





_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] **NEXT WEEK** Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On Mon, 15 May 2017, Niall Douglas via Boost wrote:

>> The vocabulary in the slides is odd (any memory is called stack,
>> anything 64 bits is called SSE) and there are some questionable
>> statements. Taking a gcc dev point of view, the main information I got
>> form those slides is interest in PR 59521 and some small margin of
>> progress on copying constant strings.
>>
>> If anything, the section on static branch prediction advertises that one
>> should use __builtin_expect more ;-)
>
> I am not the author of the talk. I can say he checked the contents of
> this thread and had a few colourful things to say about it, but did not
> disagree with my recollection of what he said.
>
> As I mentioned before, he's a long time attendee and presenter at ACCU.
> I am inclined to believe whatever he claims, he knows his stuff.

Ok, if what he said is different from what he wrote in the slides, all I
can do is trust you...

Thanks again for forwarding the link to the slides,

--
Marc Glisse

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
> I know that, which is why I'd prefer the removal to proceed to its
> logical conclusion. :-)
>
>> Are you referring to .get() and .value()?
>
> Not just that; is_ready, get_or, set_*, op->, op*, get_error, get_error_or.

I'll accept the .is_ready(), .get_or(), get_error_or(). Logged to
https://github.com/ned14/boost.outcome/issues/19

The op-> and op* are present in expected and optional. I dislike their
reinterpret_cast semantics as much as you do, but if I removed them end
users would complain.

The set_*() functions save considerable typing and boilerplate.

The .get_error() and .get_exception() I may do the same thing as I have
proposed for .get() whereby they mean "do the same default actions as
the non-get edition, but don't return reference to state". I'd love to
know reviewers' opinion on that, including whether to mark the non-get
function with [[nodiscard]].

>> > I'd even remove value_or, there's nothing wrong with r? r.value(): def.
>>
>> Both optional and expected have .value_or().
>
> Yeah, they are also wrong in having it. You/we don't need to copy
> std::optional. It's not a good example to follow.

I think such convenience member functions harmless, apart possibly from
increasing cognitive load. And users don't have to use them if they
don't want to.

But again, I'd be interested to see how many others think .value_or()
needs to die, and similarly for .error_or() and .exception_or().

>> Alas Expected and Outcome permit usage with types with no default
>> constructor, no copy nor move.
>
> This would rely on guaranteed return value elision and return {
> in_place, args... }, I suppose?

We don't need to depend on guaranteed return value elision. There is an
emplacing constructor, an initializer_list constructor, and the
observers return references. So one does not need a default constructor,
nor copy nor move.

> If these classes at some point enter the standard, the committee will
> inevitably adorn them with all this beauty, but until then, no need to
> prematurely do that ourselves.

I have no intent for any of the Outcome refinements to enter the
standard. Expected is plenty enough for the standard as a primitive
which can be built upon and extended. I deliberately have made sure that
a result<T> is commensurate to an expected<T> so AFIO v2, if it ever
goes to be standardised, can be based around expected<T>.

I do intend to submit Outcome for SG14's collection of low latency
libraries in the non-standards-proposal category.

>> BTW, is everyone aware that expected<void, void> is legal?
>
> I wasn't aware that E could be void. Which reminds me to ask you, do you
> really drop the value on the floor when converting from <T> to <void>?
> This seems like something to avoid. The value is probably important.

You cannot convert, even explicitly, from any Outcome-y <T> transport to
a <void> transport. It's disallowed because it causes data loss.

You must either manually extract and repack the E into a new <void>
transport, or there is a free function as_void() which will do it for
you. The latter should produce tighter code and compile faster, it uses
special magic type sugar to bypass implementation as
BOOST_OUTCOME_TRY(v, expr) always returns a void converted edition of
expression, and in real world usage you will using a lot of
BOOST_OUTCOME_TRY(v, expr) so it needs to be light on compile times.

BTW I leave for a business trip other side of the country tomorrow and
Wednesday. Expect no replies here until Thursday.

Niall

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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] **NEXT WEEK** Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
>> I strongly feel that name "monad" need to be renamed :)
>> Proposed alternatives:
>>
>>    - `basic_monad` -> `outcome_base` or `basic_outcome`
>>    - `monad_error` -> `bad_outcome` or `outcome_error`
>
> +1
>
> monad == FUD :-(
>
> basic_monad --> basic_outcome
>
> monad_error --> bad_outcome

Ok, that's the third vote. The change will be made. Logged to
https://github.com/ned14/boost.outcome/issues/20

Niall

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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Niall Douglas wrote:

> We don't need to depend on guaranteed return value elision. There is an
> emplacing constructor, an initializer_list constructor, and the observers
> return references. So one does not need a default constructor, nor copy
> nor move.

How are you going to return it from a function then? That's what these types
are, function return values.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
>> We don't need to depend on guaranteed return value elision. There is
>> an emplacing constructor, an initializer_list constructor, and the
>> observers return references. So one does not need a default
>> constructor, nor copy nor move.
>
> How are you going to return it from a function then? That's what these
> types are, function return values.

That's an interesting observation.

Vicente, when he reviewed Outcome's docs, was pretty appalled at how
error handling focused they are. His view is that Expected is an EITHER
monad where E is exactly like T, and he was not happy that Outcome
presents Expected as if it is solely for use for returning stuff from
functions.

And, he is right. Expected has a raft of other uses especially in
functional metaprogramming, and Outcome and its docs does not do justice
to any of those other uses.

But my counter argument is that 70-80% of people out there currently
don't care about those other uses. I know this from having to completely
rewrite the Outcome docs three times. They currently only want to know
about error handling. So I made the docs all about that only.

A non-copyable nor moveable expected<T, E> is no use for returning stuff
from functions, but I can see that such a thing might be useful for
other stuff e.g. a less awkward to use std::variant for some limited set
of variant types. I haven't given it a huge amount of thought yet to be
honest, but the Expected proposal document is very clear that
non-copyable and non-moveable types are permitted.

Niall

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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
Niall Douglas wrote:

> Vicente, when he reviewed Outcome's docs, was pretty appalled at how error
> handling focused they are. His view is that Expected is an EITHER monad
> where E is exactly like T, and he was not happy that Outcome presents
> Expected as if it is solely for use for returning stuff from functions.
>
> And, he is right.

No, he isn't. The whole point of expected<> is that T is not like E. That's
why T is _expected_, and E is _unexpected_. It's in the name.

When T is like E, you use variant<T, E>. Or variant<E, T>.

My own idea of expected<T, E...> takes one T and an arbitrary amount of Es,
and while all Es are alike, T isn't.

And this aside, the general idea is to provide alternative to exceptions,
which kind of implies returning stuff from functions, does it not?


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
>> Vicente, when he reviewed Outcome's docs, was pretty appalled at how
>> error handling focused they are. His view is that Expected is an
>> EITHER monad where E is exactly like T, and he was not happy that
>> Outcome presents Expected as if it is solely for use for returning
>> stuff from functions.
>>
>> And, he is right.
>
> No, he isn't. The whole point of expected<> is that T is not like E.
> That's why T is _expected_, and E is _unexpected_. It's in the name.
>
> When T is like E, you use variant<T, E>. Or variant<E, T>.
>
> My own idea of expected<T, E...> takes one T and an arbitrary amount of
> Es, and while all Es are alike, T isn't.
>
> And this aside, the general idea is to provide alternative to
> exceptions, which kind of implies returning stuff from functions, does
> it not?

As you might guess, Vicente would say that Expected *can* be used for
returning stuff from functions, but also a long list of other stuff.

But I won't put words in his mouth. He is subscribed here too after all,
he can answer himself if he chooses to.

Outcome doesn't get a ton of choice with its Expected implementation.
Either it implements the Expected proposal for standardisation, or it
doesn't. I don't want the Outcome refinements to veer too strongly away
from LEWG Expected, they ought to be similar, except where it's
necessary to be different, in order to make it cognitively easy for end
users. Even where I personally think Expected is making a mistake.

As much as I've kicked up a fuss in some places by intentionally
deviating from LEWG Expected to force some attention at where I think
there are problems, after this review I'll go ahead and conform as
tightly as I reasonably can and I'll track the LEWG proposal over time.
A deviating implementation muddies the waters, is confusing for end
users, and helps no one.

BTW Outcome's Expected now lives in an experimental namespace on develop
branch. I'll post a full set of changes already logged in this
pre-review when the review officially starts on Friday so people don't
waste time repeating things already logged by others.

Niall

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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
Niall Douglas wrote:

> As much as I've kicked up a fuss in some places by intentionally deviating
> from LEWG Expected to force some attention at where I think there are
> problems, after this review I'll go ahead and conform as tightly as I
> reasonably can and I'll track the LEWG proposal over time. A deviating
> implementation muddies the waters, is confusing for end
users, and helps no one.

A conforming expected<> is fine, but result<> and outcome<> do not have to
provide the same interface. I'd rather see them address the function return
use case in a clean, efficient, clutter-free way, rather than trying to be
something else.

(I'd also rather see expected<> address that same use case instead of trying
to be usable as a long list of something else, but that's, as you would say,
out of scope for this review.)


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 16/05/2017 03:48, Niall Douglas wrote:

> Are you referring to .get() and .value()?
>
> I use a convention of .value() in my own code to indicate when I am
> retrieving the value, and .get() to indicate I am throwing away the
> fetched value but I do want any default actions to occur e.g. if not
> valued, throw an exception. So .get() means "fetch and throw any error
> state if present".
>
> If people like this convention, I can make it formal by tagging
> .value()'s return with [[nodiscard]] and have .get() return void. If
> people dislike this convention, .get() can be removed.
>
> I really wasn't sure what people might prefer. [[nodiscard]] is so new
> it's hard to decide on if we are using it overkill or not. I look
> forward to any feedback.

Maybe I'm missing some context, but unless T is void, making a void
get() method seems very peculiar to me.  Logically a get method should
actually get something.

(void get() where T is void is also weird, but at least its behaviour is
familiar to anyone used to futures, and is reasonably orthogonal to the
non-void T case, and has some benefits to *some* generic code -- though
sadly void is still a second-class citizen in the type system.)



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
Gavin Lambert wrote:

> Maybe I'm missing some context, but unless T is void, making a void get()
> method seems very peculiar to me.  Logically a get method should actually
> get something.

get() is not a very good name, it's more like ensure(), and the intended use
is in the transition from an outcome<>-using layer to a throwing layer:

T f() // throws
{
    outcome<X> o1 = f1_impl(); // doesn't throw
    o1.ensure(); // ensure we have a value

    outcoume<Y> o2 = f2_impl();
    o2.ensure();

    return { *o1, *o2 };
}

The reference access paradigm implies that we want to keep the values in the
outcomes, so there's no need to actually extract them, we can use them
in-place.

In contrast, the value return paradigm implies that in this scenario we want
to extract the values from the outcomes and throw the outcomes away:

T f()
{
    X x = f1_impl().value();
    Y y = f2_impl().value();

    return { x, y };
}

No need for a void get() here. Or, if we want to be verbose:

T f()
{
    outcome<X> o1 = f1_impl();
    X x = std::move(o1).value();

    outcome<Y> o2 = f2_impl();
    Y y = std::move(o2).value();

    return { x, y };
}

although in this case o1 and o2 stay in scope and we prefer them not to
because we don't want to access them after the values have been extracted.
It's more explicit though so to each his own.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
On 16/05/2017 11:47, Peter Dimov wrote:

> Gavin Lambert wrote:
>
>> Maybe I'm missing some context, but unless T is void, making a void
>> get() method seems very peculiar to me.  Logically a get method should
>> actually get something.
>
> get() is not a very good name, it's more like ensure(), and the intended
> use is in the transition from an outcome<>-using layer to a throwing layer:
>
> T f() // throws
> {
>    outcome<X> o1 = f1_impl(); // doesn't throw
>    o1.ensure(); // ensure we have a value
>
>    outcoume<Y> o2 = f2_impl();
>    o2.ensure();
>
>    return { *o1, *o2 };
> }
>
> The reference access paradigm implies that we want to keep the values in
> the outcomes, so there's no need to actually extract them, we can use
> them in-place.
>
> In contrast, the value return paradigm implies that in this scenario we
> want to extract the values from the outcomes and throw the outcomes away:
>
> T f()
> {
>    X x = f1_impl().value();
>    Y y = f2_impl().value();
>
>    return { x, y };
> }

Surely this must also throw if f1_impl() can produce an error outcome
and thus might not contain an X?  I don't see the distinction.

(Use of outcome<X> above implies that X is not itself an error-capable
type.)



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
Gavin Lambert wrote:

> Surely this must also throw if f1_impl() can produce an error outcome and
> thus might not contain an X?

Yes of course, the examples are deliberately identical semantically, one
uses "void get()" and the other uses "T value()". I prefer the second.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
2017-05-16 1:47 GMT+02:00 Peter Dimov via Boost <[hidden email]>:

> Gavin Lambert wrote:
>
> Maybe I'm missing some context, but unless T is void, making a void get()
>> method seems very peculiar to me.  Logically a get method should actually
>> get something.
>>
>
> get() is not a very good name, it's more like ensure(), and the intended
> use is in the transition from an outcome<>-using layer to a throwing layer:
>
> T f() // throws
> {
>    outcome<X> o1 = f1_impl(); // doesn't throw
>    o1.ensure(); // ensure we have a value
>
>    outcoume<Y> o2 = f2_impl();
>    o2.ensure();
>
>    return { *o1, *o2 };
> }
>
> The reference access paradigm implies that we want to keep the values in
> the outcomes, so there's no need to actually extract them, we can use them
> in-place.
>
> In contrast, the value return paradigm implies that in this scenario we
> want to extract the values from the outcomes and throw the outcomes away:
>
> T f()
> {
>    X x = f1_impl().value();
>    Y y = f2_impl().value();
>
>    return { x, y };
> }
>
> No need for a void get() here. Or, if we want to be verbose:
>
> T f()
> {
>    outcome<X> o1 = f1_impl();
>    X x = std::move(o1).value();
>
>    outcome<Y> o2 = f2_impl();
>    Y y = std::move(o2).value();
>
>    return { x, y };
> }
>
> although in this case o1 and o2 stay in scope and we prefer them not to
> because we don't want to access them after the values have been extracted.
> It's more explicit though so to each his own.


It's interesting. Only after Peter's explanation I am able to see the
usefulness of outcome<>, at least this part of the interface. It looks like
you - Peter - have the understanding of Niall's intentions. And I am
clearly lacking them. I would not be able to figure out this use case from
the tutorials of the reference.

This gives me the impression that the library has a big potential, but it
may not succeed because of the failure to explain its power to potential
users.

It would really be helpful to see a section in the docs with a number of
examples simple as the ones above, explaining different use cases. I am
still missing how the tribool logic can be used: in if-statements?

```
if (o1 || o2) ... // is that it?
```

Regards,
&rzej;

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 16/05/2017 13:50, Peter Dimov wrote:
>> Surely this must also throw if f1_impl() can produce an error outcome
>> and thus might not contain an X?
>
> Yes of course, the examples are deliberately identical semantically, one
> uses "void get()" and the other uses "T value()". I prefer the second.

Future uses "T get()".  This is established standard.
Smart pointers use "T* get()", which is equivalent to the above.  Also
standard.
Boost Optional uses "T& get()" (although also provides value(),
presumably for standard compatibility).

Std Optional uses "T value()".  This is either still experimental or
approved for C++17; I'm not entirely sure how far along that is.

The different interfaces of the above seem unfortunate (and Std Optional
seems incorrect in this regard to me).

So why not "T get()"?  That's much more consistent with other types.



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
Gavin Lambert wrote:
> Future uses "T get()".  This is established standard.
> Smart pointers use "T* get()", which is equivalent to the above.  Also
> standard.
> Boost Optional uses "T& get()" (although also provides value(), presumably
> for standard compatibility).
>
> Std Optional uses "T value()".  This is either still experimental or
> approved for C++17; I'm not entirely sure how far along that is.

It's in C++17.

> The different interfaces of the above seem unfortunate (and Std Optional
> seems incorrect in this regard to me).
>
> So why not "T get()"?  That's much more consistent with other types.

.get() is when you only have one thing to get; it's for one-element
containers, where there's no ambiguity as to what is being got.

expected<T, E> and friends have two; the value is .value() and the error is
.error(), with their matching queries has_value() and has_error().

It's not that get() is unacceptably wrong, but the
value/has_value/error/has_error convention is legitimate and consistent.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
On 17/05/2017 11:34, Peter Dimov wrote:
>> So why not "T get()"?  That's much more consistent with other types.
>
> .get() is when you only have one thing to get; it's for one-element
> containers, where there's no ambiguity as to what is being got.
>
> expected<T, E> and friends have two; the value is .value() and the error
> is .error(), with their matching queries has_value() and has_error().

But by definition these are not treated equally.  The value is the
expected thing (thus get() makes sense to retrieve it) and the error or
exception are the unexpected things (thus some other method).  I don't
see any ambiguity there.

> It's not that get() is unacceptably wrong, but the
> value/has_value/error/has_error convention is legitimate and consistent.

Having "T value()" as the only API is fine, but seems a bit inconsistent
as that's not the common verb used by other types (in fact it's not even
a verb).  (std::get is another argument in favour of this.)

Having "T value()" and "T get()" is ok (it's sort of like Boost Optional
that way) but it's a bit redundant and it would just make people
second-guess which one they should use, or if they're different in some way.

Having "T value()" and "void get()" is just bananas.  Though for Niall's
proposed usage, perhaps "void ensure()" would make sense.

Regarding [[nodiscard]], I don't think either of these methods should
have that.  Instead it should be the method that returns the expected<>
or outcome<> that declares its return value to be [[nodiscard]] (if it
wishes).

Though I recall another proposed library using some trick (possibly
involving rvalue-methods?) to ensure a compiler error if the return
value was uninspected without explicitly using [[nodiscard]].



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Le 16/05/2017 à 00:22, Peter Dimov via Boost a écrit :
> Niall Douglas wrote:
>
>> Vicente, when he reviewed Outcome's docs, was pretty appalled at how
>> error handling focused they are. His view is that Expected is an
>> EITHER monad where E is exactly like T, and he was not happy that
>> Outcome presents Expected as if it is solely for use for returning
>> stuff from functions.
No I have never said that E is like T.

>>
>> And, he is right.
>
> No, he isn't. The whole point of expected<> is that T is not like E.
> That's why T is _expected_, and E is _unexpected_. It's in the name.
>
> When T is like E, you use variant<T, E>. Or variant<E, T>.
>
> My own idea of expected<T, E...> takes one T and an arbitrary amount
> of Es, and while all Es are alike, T isn't.
>
> And this aside, the general idea is to provide alternative to
> exceptions, which kind of implies returning stuff from functions, does
> it not?
I agree completly.

expected<T, E...> is IMO the same as expected<T, variant<E...>> except
that it could add some syntactic sugar. I'll not be against a
expected<T, E...>.

The way either E T is used in Haskell is exactly this one. Note that
with TypeClasses a type as variant <T, E...> can be seen in a lot of
different ways.

Vicente



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Le 16/05/2017 à 00:48, Niall Douglas via Boost a écrit :

>>> Vicente, when he reviewed Outcome's docs, was pretty appalled at how
>>> error handling focused they are. His view is that Expected is an
>>> EITHER monad where E is exactly like T, and he was not happy that
>>> Outcome presents Expected as if it is solely for use for returning
>>> stuff from functions.
>>>
>>> And, he is right.
>> No, he isn't. The whole point of expected<> is that T is not like E.
>> That's why T is _expected_, and E is _unexpected_. It's in the name.
>>
>> When T is like E, you use variant<T, E>. Or variant<E, T>.
>>
>> My own idea of expected<T, E...> takes one T and an arbitrary amount of
>> Es, and while all Es are alike, T isn't.
>>
>> And this aside, the general idea is to provide alternative to
>> exceptions, which kind of implies returning stuff from functions, does
>> it not?
> As you might guess, Vicente would say that Expected *can* be used for
> returning stuff from functions, but also a long list of other stuff.
>
> But I won't put words in his mouth. He is subscribed here too after all,
> he can answer himself if he chooses to.
Thanks Niall. I can speak for myself.
Vicente



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [review] Review of Outcome (starts Fri-19-May)

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
> It's interesting. Only after Peter's explanation I am able to see the
> usefulness of outcome<>, at least this part of the interface. It looks like
> you - Peter - have the understanding of Niall's intentions. And I am
> clearly lacking them. I would not be able to figure out this use case from
> the tutorials of the reference.
>
> This gives me the impression that the library has a big potential, but it
> may not succeed because of the failure to explain its power to potential
> users.

This has been a persistent problem over the past year.

Once you've been using these things in your own code for a bit, for
especially low level systems libraries you'd never willingly go back.
The difference is very similar (to me at least) to that feeling you have
when you must go back to writing C++ 98 without Boost after you've been
using C++ 14 for a quite a while.

All that said, 60-70% of C++ would see no benefit to using Outcome nor
Expected. Such code is always better off using only C++ exceptions.

> It would really be helpful to see a section in the docs with a number of
> examples simple as the ones above, explaining different use cases.

I am hesitant to add even more length to the existing documentation.
It's already long enough to put people off.

A refactoring and shortening of the current length would be much more
desirable.

> I am
> still missing how the tribool logic can be used: in if-statements?
>
> ```
> if (o1 || o2) ... // is that it?
> ```

Outcome provides both binary and ternary conversion operators.
Unqualified usage in an if statement will use the binary edition which
is true iff state is valued, false otherwise. If you compare an outcome
to a tribool, you'll use the ternary edition, there you can test against
true, false, and other.

If ternary logic suits your use case, using it can make your code much
clearer. Other use cases would do better testing .has_value(),
.has_error() and .empty() explicitly. Still other use cases would do
better to dispatch to a function overload based on the current type of
the state.

Niall

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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
123456
Loading...