Topic: Thoughts on Exceptions, Expected, and Error Handling
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 2 Jun 2015 22:09:15 -0700 (PDT)
Raw View
------=_Part_668_1580123715.1433308155099
Content-Type: multipart/alternative;
boundary="----=_Part_669_1356499203.1433308155100"
------=_Part_669_1356499203.1433308155100
Content-Type: text/plain; charset=UTF-8
After reading through various people's ideas about how to go about reporting
errors from number parsing systems
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MJIRnrc7vbo/jGO0zjXQrEYJ>,
as well as writing a preliminary document on the variety of error reporting
mechanisms
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/G1YheYoGznw/7AuxvrJhv6gJ>
in applications and libraries at present, I've come to some thoughts and
conclusions on how error reporting and resolution ought to be handled.
When I analyzed the various error reporting mechanisms, I did so along
three independent axes: local error resolution, non-local error resolution,
and local error ignoring. What I came to realize is that, generally
speaking, in the event of an error condition, code does one of the
following: the error is resolved by the code that directly generated it;
the error is resolved by someone else; or the program forges ahead,
blissfully unaware of an error. That may sound obvious, but it's an
important point.
The thing that set my mind to this was with the whole number parsing thing.
In there, people made a strong case for `expected`, but these cases were
always in the context of local error resolution. The function that was
directly calling the `parse_integer` function would be resolving the
ensuing error.
The argument being that parse errors are expected; they're entirely
natural. So it's expected that the local caller will field such errors, and
if the caller doesn't, then the local caller has decided effectively not to
care. In such an event, throwing an exception is warranted. So `expected`
seems quite ideal in such circumstances; if you try to fetch the value
without checking that it's there, the system will throw a wrapped error
code.
This seems ideal, but there are many flaws with such an approach. For
example, this approach assumes that the local caller function is actually
capable of resolving this kind of error. The farther up the call graph one
has to search to resolve an `expected` error, the more difficult it gets to
get the `expected` error where it needs to go.
As an example, consider `parse_integer`. If `parse_integer` has no
knowledge of filesystem IO, then it is reasonable for a user to write a
function that can take a file IO object and parse integers from it. Call
this `file_parse_integer`; it reads some number of non-space characters
from a file stream, passes the string to `parse_integer` and then
returns... what?
It cannot return `expected<int, parse_error>`. Why? Because
`file_parse_integer` can now fail for two *separate* reasons: a failure to
parse the characters, and a failure to *read the characters from the file
stream*. The only legitimate thing that `file_parse_integer` can do is
return both possibilities: `expected<int, variant<parse_error,
file_error>>`. If both the file reading error and the parse error use
`std::error_condition`, then at least the variant can be avoided. But
regardless of how the error is returned, the direct caller is required to
field all of the cases. But not just all of the parse error cases; he must
field all of the file reading cases too.
One might say that this is still true even if using exceptions, but I
contest this for one very important reason: file reading errors usually
represent a fundamentally different kind of problem than parsing errors. If
an integer parse fails, that could be reasonably expected by the user and
handled locally. If a file fails to read at all, this is not a problem that
someone who's expecting to read an integer can resolve; it can only be
effectively resolved by higher level code. The system that began this
entire "parse stuff from a file" needs to be notified that it failed. How
many levels high is that system? Who knows.
Is it reasonable for callers of `file_parse_integer` to have to manually
propagate that error all the way back?
Next, one might say that this is a special case, that filesystem errors are
always a different kind of thing, something which is rare and thus clearly
ought to be handled by exceptions. That is not an unreasonable argument.
However, there are times when parse errors can logically be treated in the
same light. This would be in a file format that you the programmer have
fundamental control over, who's contents are generated by internal code,
not the user. To that user, parse errors are not a normal thing; they're an
exceptional circumstance. If there's a parse error, this user wants to
completely shut down all processing of this data, under the presumption
that something truly terrible has happened in the system. Perhaps to the
point of rolling back any changes made based on this data, since it must
now be considered suspect.
If this code were using `file_parse_integer`, it would react to a parse
error in the exact same way it reacts to a filesystem error: halt the
process at its source, undo anything that was done, and resume normal
functionality.
Is it reasonable for this user to have to manually return `expected`
objects or failure error codes, just to be able to get the error where it
needs to go?
So in one case, we have a user who has a genuine reason to want file
reading errors to be exceptions, but would probably want actual parse
errors to be `expected`s. While the other use wants both of them to be
exceptions.
You might say that it's fine, because if you get the `expected` value
without checking it, an exception will be thrown if it isn't there. And
that is true.
But let us consider the nature of that exception.
The most recent proposal of `expected`
<http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4109.pdf>
basically has two variations: one for arbitrary error code objects and one
for `exception_ptr`. In the latter case, the `exception_ptr` is thrown as
that exception. In the former case, a template class is thrown, based on
the type for the error code used by the `expected`. Now,
std::error_condition can do quite a bit of stuff, based on the base
`std::error_category` class it uses.
However, everything that `error_condition` can do is based purely on the
type of `error_category` it uses and an integer. Now, consider parsing
integers. If a parse error occurs, the parsing system knows a lot of very
useful information about it. It knows how many characters it successfully
read. It knows exactly which character caused that error. And so forth.
All of that information is *lost* when you reduce the error to a number.
Certainly, `expected` can store something more than an `error_condition`
(basically, an integer and a pointer). But if you start throwing around an
`expected<int, big_giant_object>`, that's a huge cost to be paid compared
to just an `int`. It's bad enough that `expected<int, error_condition>`, on
64-bit builds, is approaching a 32-byte cache-line in size; to make the
object even bigger is crazy. And if you need to propagate that out of the
local scope, that's a big object to be returning up the callstack.
For local error handling, providing little information is reasonable,
because local code actually knows the context of the error. It knows what
the input string was, the range of characters passed to `parse_integer`.
Also, the return value(s) from `parse_integer` may include an offset to the
parsed character, in some form.
However, if an error needs to be propagated, simply inducing `expected` to
throw an exception via `.value()` is... rather useless when needing to
actually report a problem. Oh sure, you can use `error_condition::message`
to be told something about why the text didn't parse. But you know *nothing*
about where this happened; that information was lost when the local scope
returned the error code. You lose lots of very useful knowledge.
By contrast, a `parse_integer` that natively fires off an exception can
encapsulate useful information. It can say exactly where this error took
place in the given string. It can even store the given string in the
exception, as reference. And so forth. Information that would have been
lost to the local scope can now be granted to a higher scope.
This was a problem (one of many) with a suggestion that was made in another
thread to have the FileSystem TS do away with exceptions *entirely*,
relying solely on `expected` for error handling
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/4MErTLraVDg/fK9pPtRgXRAJ>.
The `filesystem_error` class is quite rich in information as to exactly
where a problem happened, able to store and return entire `path` objects
that represent parameters to various error-generating functions. For local
error resolving, this seems like overkill. But for handling errors at a
higher level? This is exactly the kind of information that would be lost
and can be critical for finding out where a problem is.
Consider the prior discussed case of a `parse_integer` function, where a
parse error represents a fundamental failure of the entire process of
parsing this data, causing a rollback of changes made based on it. If you
need to log information based on this parse error, the exception case can
give you something that's actually useful. The `expected` case simply says,
"Found a letter instead of a number".
Now, you could say that all `parse_integer` could store would be
information that's locally available: the string parameter. It wouldn't
know how many strings had already been processed or anything. And that is
true; to get more information, you would need to do some exception
translation, using specific knowledge at each layer to add new information.
In that case, you have some local pre-processing of error information,
massaging it into the most useful form for consumption. And this is
starting to resemble the `expected` case, where every layer between the
erroring function and the handler must know about these errors and
propagate them explicitly in code. However, this way, you get to use an
actual object, rather than having to fit things into an `error_condition`.
Yes, `expected` could use any object; however, as previously discussed, if
multiple paths of code need to propagate multiple errors up the same
function, `error_condition` is pretty much the only sane way to go. Unless
you like sorting through `variants`.
The exception case is so much cleaner, even with having to do translation
at various layers. Only layers that actually do translation need to be
involved in that process; otherwise, the code is clean.
And then there are things that `expected` flat-out cannot handle or handles
very poorly.
The first is any function that doesn't return a value. Oh yes,
`expected<void, ec>` exists. But it would be rather... foolish to expect
everyone to do that. Uniformly.
The same applies to any function that returns a value that most users will
drop on the floor. `filesystem::create_directory` is a good example. Most
people will just assume it succeeded. But only in the exception case will
they be forced to confront the possibility of failure.
To be fair to `expected`, the latter two can be helped via external tools.
It would be possible, particularly with Clang, to write a tool that scans
for `expected` return values that are discarded.
The more extreme case is object construction, for which the C++ standard
has no solution other than exceptions. Options like `expected(in_place_t)`
don't really work. You lose "uniform" initialization syntax, as you can't
access the initializer_list constructor with {}. It's a nice try, and is
necessary for initializing immobile types. But it doesn't work nearly as
well as a straight constructor. And most importantly of all, it doesn't
actually capture any exceptions thrown by `T`'s constructor.
That all brings me to a number of conclusions:
1) Exceptions work best in non-local error handling contexts. Local error
handling best works via `expected`, except where `expected` cannot be used
or is poor at the job.
2) The difference between local and non-local handling *cannot be known to
the library*. It may guess and hope, but there are usually legitimate cases
where a user might handle errors one way or the other.
3) Where possible, allow the user to decide whether errors are handled
locally or not. As such, functions that error should have two versions: one
that throws and one that uses `expected`.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_669_1356499203.1433308155100
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">After reading through various people's ideas about how to =
go about <a href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-propos=
als/MJIRnrc7vbo/jGO0zjXQrEYJ">reporting errors from number parsing systems<=
/a>, as well as writing a <a href=3D"https://groups.google.com/a/isocpp.org=
/d/msg/std-proposals/G1YheYoGznw/7AuxvrJhv6gJ">preliminary document on the =
variety of error reporting mechanisms</a> in applications and libraries at =
present, I've come to some thoughts and conclusions on how error reporting =
and resolution ought to be handled.<br><br>When I analyzed the various erro=
r reporting mechanisms, I did so along three independent axes: local error =
resolution, non-local error resolution, and local error ignoring. What I ca=
me to realize is that, generally speaking, in the event of an error conditi=
on, code does one of the following: the error is resolved by the code that =
directly generated it; the error is resolved by someone else; or the progra=
m forges ahead, blissfully unaware of an error. That may sound obvious, but=
it's an important point.<br><br>The thing that set my mind to this was wit=
h the whole number parsing thing. In there, people made a strong case for `=
expected`, but these cases were always in the context of local error resolu=
tion. The function that was directly calling the `parse_integer` function w=
ould be resolving the ensuing error.<br><br>The argument being that parse e=
rrors are expected; they're entirely natural. So it's expected that the loc=
al caller will field such errors, and if the caller doesn't, then the local=
caller has decided effectively not to care. In such an event, throwing an =
exception is warranted. So `expected` seems quite ideal in such circumstanc=
es; if you try to fetch the value without checking that it's there, the sys=
tem will throw a wrapped error code.<br><br>This seems ideal, but there are=
many flaws with such an approach. For example, this approach assumes that =
the local caller function is actually capable of resolving this kind of err=
or. The farther up the call graph one has to search to resolve an `expected=
` error, the more difficult it gets to get the `expected` error where it ne=
eds to go.<br><br>As an example, consider `parse_integer`. If `parse_intege=
r` has no knowledge of filesystem IO, then it is reasonable for a user to w=
rite a function that can take a file IO object and parse integers from it. =
Call this `file_parse_integer`; it reads some number of non-space character=
s from a file stream, passes the string to `parse_integer` and then returns=
.... what?<br><br>It cannot return `expected<int, parse_error>`. Why? =
Because `file_parse_integer` can now fail for two <i>separate</i> reasons: =
a failure to parse the characters, and a failure to <i>read the characters =
from the file stream</i>. The only legitimate thing that `file_parse_intege=
r` can do is return both possibilities: `expected<int, variant<parse_=
error, file_error>>`. If both the file reading error and the parse er=
ror use `std::error_condition`, then at least the variant can be avoided. B=
ut regardless of how the error is returned, the direct caller is required t=
o field all of the cases. But not just all of the parse error cases; he mus=
t field all of the file reading cases too.<br><br>One might say that this i=
s still true even if using exceptions, but I contest this for one very impo=
rtant reason: file reading errors usually represent a fundamentally differe=
nt kind of problem than parsing errors. If an integer parse fails, that cou=
ld be reasonably expected by the user and handled locally. If a file fails =
to read at all, this is not a problem that someone who's expecting to read =
an integer can resolve; it can only be effectively resolved by higher level=
code. The system that began this entire "parse stuff from a file" needs to=
be notified that it failed. How many levels high is that system? Who knows=
..<br><br>Is it reasonable for callers of `file_parse_integer` to have to ma=
nually propagate that error all the way back?<br><br>Next, one might say th=
at this is a special case, that filesystem errors are always a different ki=
nd of thing, something which is rare and thus clearly ought to be handled b=
y exceptions. That is not an unreasonable argument. However, there are time=
s when parse errors can logically be treated in the same light. This would =
be in a file format that you the programmer have fundamental control over, =
who's contents are generated by internal code, not the user. To that user, =
parse errors are not a normal thing; they're an exceptional circumstance. I=
f there's a parse error, this user wants to completely shut down all proces=
sing of this data, under the presumption that something truly terrible has =
happened in the system. Perhaps to the point of rolling back any changes ma=
de based on this data, since it must now be considered suspect.<br><br>If t=
his code were using `file_parse_integer`, it would react to a parse error i=
n the exact same way it reacts to a filesystem error: halt the process at i=
ts source, undo anything that was done, and resume normal functionality.<br=
><br>Is it reasonable for this user to have to manually return `expected` o=
bjects or failure error codes, just to be able to get the error where it ne=
eds to go?<br><br>So in one case, we have a user who has a genuine reason t=
o want file reading errors to be exceptions, but would probably want actual=
parse errors to be `expected`s. While the other use wants both of them to =
be exceptions.<br><br>You might say that it's fine, because if you get the =
`expected` value without checking it, an exception will be thrown if it isn=
't there. And that is true.<br><br>But let us consider the nature of that e=
xception.<br><br>The <a href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs=
/papers/2014/n4109.pdf">most recent proposal of `expected`</a> basically ha=
s two variations: one for arbitrary error code objects and one for `excepti=
on_ptr`. In the latter case, the `exception_ptr` is thrown as that exceptio=
n. In the former case, a template class is thrown, based on the type for th=
e error code used by the `expected`. Now, std::error_condition can do quite=
a bit of stuff, based on the base `std::error_category` class it uses.<br>=
<br>However, everything that `error_condition` can do is based purely on th=
e type of `error_category` it uses and an integer. Now, consider parsing in=
tegers. If a parse error occurs, the parsing system knows a lot of very use=
ful information about it. It knows how many characters it successfully read=
.. It knows exactly which character caused that error. And so forth.<br><br>=
All of that information is <i>lost</i> when you reduce the error to a numbe=
r.<br><br>Certainly, `expected` can store something more than an=20
`error_condition` (basically, an integer and a pointer). But if you=20
start throwing around an `expected<int, big_giant_object>`, that's
a huge cost to be paid compared to just an `int`. It's bad enough that `ex=
pected<int, error_condition>`, on 64-bit builds, is approaching a 32-=
byte cache-line in size; to make the object even bigger is crazy. And if yo=
u need to propagate that out of the=20
local scope, that's a big object to be returning up the callstack.<br><br>F=
or local error handling, providing little information is reasonable, becaus=
e local code actually knows the context of the error. It knows what the inp=
ut string was, the range of characters passed to `parse_integer`. Also, the=
return value(s) from `parse_integer` may include an offset to the parsed c=
haracter, in some form.<br><br>However, if an error needs to be propagated,=
simply inducing `expected` to throw an exception via `.value()` is... rath=
er useless when needing to actually report a problem. Oh sure, you can use =
`error_condition::message` to be told something about why the text didn't p=
arse. But you know <i>nothing</i> about where this happened; that informati=
on was lost when the local scope returned the error code. You lose lots of =
very useful knowledge.<br><br>By contrast, a `parse_integer` that natively =
fires off an exception can encapsulate useful information. It can say exact=
ly where this error took place in the given string. It can even store the g=
iven string in the exception, as reference. And so forth. Information that =
would have been lost to the local scope can now be granted to a higher scop=
e.<br><br>This was a problem (one of many) with a suggestion that was made =
in another thread to have <a href=3D"https://groups.google.com/a/isocpp.org=
/d/msg/std-proposals/4MErTLraVDg/fK9pPtRgXRAJ">the FileSystem TS do away wi=
th exceptions <i>entirely</i>, relying solely on `expected` for error handl=
ing</a>. The `filesystem_error` class is quite rich in information as to ex=
actly where a problem happened, able to store and return entire `path` obje=
cts that represent parameters to various error-generating functions. For lo=
cal error resolving, this seems like overkill. But for handling errors at a=
higher level? This is exactly the kind of information that would be lost a=
nd can be critical for finding out where a problem is.<br><br>Consider the =
prior discussed case of a `parse_integer` function, where a parse error rep=
resents a fundamental failure of the entire process of parsing this data, c=
ausing a rollback of changes made based on it. If you need to log informati=
on based on this parse error, the exception case can give you something tha=
t's actually useful. The `expected` case simply says, "Found a letter inste=
ad of a number".<br><br>Now, you could say that all `parse_integer` could s=
tore would be information that's locally available: the string parameter. I=
t wouldn't know how many strings had already been processed or anything. An=
d that is true; to get more information, you would need to do some exceptio=
n translation, using specific knowledge at each layer to add new informatio=
n.<br><br>In that case, you have some local pre-processing of error informa=
tion, massaging it into the most useful form for consumption. And this is s=
tarting to resemble the `expected` case, where every layer between the erro=
ring function and the handler must know about these errors and propagate th=
em explicitly in code. However, this way, you get to use an actual object, =
rather than having to fit things into an `error_condition`. Yes, `expected`=
could use any object; however, as previously discussed, if multiple paths =
of code need to propagate multiple errors up the same function, `error_cond=
ition` is pretty much the only sane way to go. Unless you like sorting thro=
ugh `variants`.<br><br>The exception case is so much cleaner, even with hav=
ing to do translation at various layers. Only layers that actually do trans=
lation need to be involved in that process; otherwise, the code is clean.<b=
r><br>And then there are things that `expected` flat-out cannot handle or h=
andles very poorly.<br><br>The first is any function that doesn't return a =
value. Oh yes, `expected<void, ec>` exists. But it would be rather...=
foolish to expect everyone to do that. Uniformly.<br><br>The same applies =
to any function that returns a value that most users will drop on the floor=
.. `filesystem::create_directory` is a good example. Most people will just a=
ssume it succeeded. But only in the exception case will they be forced to c=
onfront the possibility of failure.<br><br>To be fair to `expected`, the la=
tter two can be helped via external tools. It would be possible, particular=
ly with Clang, to write a tool that scans for `expected` return values that=
are discarded.<br><br>The more extreme case is object construction, for wh=
ich the C++ standard has no solution other than exceptions. Options like `e=
xpected(in_place_t)` don't really work. You lose "uniform" initialization s=
yntax, as you can't access the initializer_list constructor with {}. It's a=
nice try, and is necessary for initializing immobile types. But it doesn't=
work nearly as well as a straight constructor. And most importantly of all=
, it doesn't actually capture any exceptions thrown by `T`'s constructor.<b=
r><br><br>That all brings me to a number of conclusions:<br><br>1) Exceptio=
ns work best in non-local error handling contexts. Local error handling bes=
t works via `expected`, except where `expected` cannot be used or is poor a=
t the job.<br><br>2) The difference between local and non-local handling <i=
>cannot be known to the library</i>. It may guess and hope, but there are u=
sually legitimate cases where a user might handle errors one way or the oth=
er.<br><br>3) Where possible, allow the user to decide whether errors are h=
andled locally or not. As such, functions that error should have two versio=
ns: one that throws and one that uses `expected`.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_669_1356499203.1433308155100--
------=_Part_668_1580123715.1433308155099--
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Wed, 3 Jun 2015 15:49:41 +0200
Raw View
--Apple-Mail=_B08DE8F2-CA27-4D26-9B60-9BA06516C3CE
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> Il giorno 03/giu/2015, alle ore 07:09, Nicol Bolas <jmckesson@gmail.com> =
ha scritto:
>=20
> After reading through various people's ideas about how to go about report=
ing errors from number parsing systems <https://groups.google.com/a/isocpp.=
org/d/msg/std-proposals/MJIRnrc7vbo/jGO0zjXQrEYJ>, as well as writing a pre=
liminary document on the variety of error reporting mechanisms <https://gro=
ups.google.com/a/isocpp.org/d/msg/std-proposals/G1YheYoGznw/7AuxvrJhv6gJ> i=
n applications and libraries at present, I've come to some thoughts and con=
clusions on how error reporting and resolution ought to be handled.
>=20
> When I analyzed the various error reporting mechanisms, I did so along th=
ree independent axes: local error resolution, non-local error resolution, a=
nd local error ignoring. What I came to realize is that, generally speaking=
, in the event of an error condition, code does one of the following: the e=
rror is resolved by the code that directly generated it; the error is resol=
ved by someone else; or the program forges ahead, blissfully unaware of an =
error. That may sound obvious, but it's an important point.
>=20
Hi. Yes it is an important point indeed. Errors should not go =E2=80=9Cblis=
sfully=E2=80=9D ignored, though.
There must be a very good motivation to ignore a possible source of excepti=
ons
(see out of memory exceptions), and in my opinion the language/library shou=
ld enforce
the user to explicitly choose to ignore errors.
This is also the main fundamental difference between exceptions and expecte=
d: the default is to ignore the error in the first case,
to handle it in the second.=20
> The thing that set my mind to this was with the whole number parsing thin=
g. In there, people made a strong case for `expected`, but these cases were=
always in the context of local error resolution. The function that was dir=
ectly calling the `parse_integer` function would be resolving the ensuing e=
rror.
>=20
> The argument being that parse errors are expected; they're entirely natur=
al. So it's expected that the local caller will field such errors, and if t=
he caller doesn't, then the local caller has decided effectively not to car=
e. In such an event, throwing an exception is warranted. So `expected` seem=
s quite ideal in such circumstances; if you try to fetch the value without =
checking that it's there, the system will throw a wrapped error code.
>=20
Indeed.
> This seems ideal, but there are many flaws with such an approach. For exa=
mple, this approach assumes that the local caller function is actually capa=
ble of resolving this kind of error. The farther up the call graph one has =
to search to resolve an `expected` error, the more difficult it gets to get=
the `expected` error where it needs to go.
>=20
You=E2=80=99re not =E2=80=9Cassuming=E2=80=9D the caller is capable of reso=
lving the error: you=E2=80=99re _enforcing_ the caller to think about the e=
rror,
and _explicitly_ chose to ignore it or propagate it up if it cannot handle =
it.
> As an example, consider `parse_integer`. If `parse_integer` has no knowle=
dge of filesystem IO, then it is reasonable for a user to write a function =
that can take a file IO object and parse integers from it. Call this `file_=
parse_integer`; it reads some number of non-space characters from a file st=
ream, passes the string to `parse_integer` and then returns... what?
>=20
> It cannot return `expected<int, parse_error>`. Why? Because `file_parse_i=
nteger` can now fail for two separate reasons: a failure to parse the chara=
cters, and a failure to read the characters from the file stream. The only =
legitimate thing that `file_parse_integer` can do is return both possibilit=
ies: `expected<int, variant<parse_error, file_error>>`. If both the file re=
ading error and the parse error use `std::error_condition`, then at least t=
he variant can be avoided. But regardless of how the error is returned, the=
direct caller is required to field all of the cases. But not just all of t=
he parse error cases; he must field all of the file reading cases too.
>=20
This point ignores the distinction you made at the beginning: the parse err=
or is a natural condition, the IO error is not (in general).
So in my opinion such a case should be handled by returning an expected<int=
, parse_error> _and_ throw an exception in case
of IO errors.=20
That is exactly the distinction made by functional languages such as Haskel=
l, which as you may know make a strong distinction=20
between pure computations (parsing a file) and IO actions (reading the file=
from the stream). The hybrid interface I proposed above
mimics exactly this distinction. You=E2=80=99re explicitly dealing with the=
result of the =E2=80=9Cpure=E2=80=9D part of your code while using an out-=
of-band
channel to signal IO exceptions.
More on that a few points later.
> One might say that this is still true even if using exceptions, but I con=
test this for one very important reason: file reading errors usually repres=
ent a fundamentally different kind of problem than parsing errors. If an in=
teger parse fails, that could be reasonably expected by the user and handle=
d locally. If a file fails to read at all, this is not a problem that someo=
ne who's expecting to read an integer can resolve; it can only be effective=
ly resolved by higher level code. The system that began this entire "parse =
stuff from a file" needs to be notified that it failed. How many levels hig=
h is that system? Who knows.
>=20
That=E2=80=99s why I agree you should use exceptions for IO-related failure=
s.
> Is it reasonable for callers of `file_parse_integer` to have to manually =
propagate that error all the way back?
>=20
> Next, one might say that this is a special case, that filesystem errors a=
re always a different kind of thing, something which is rare and thus clear=
ly ought to be handled by exceptions. That is not an unreasonable argument.=
However, there are times when parse errors can logically be treated in the=
same light. This would be in a file format that you the programmer have fu=
ndamental control over, who's contents are generated by internal code, not =
the user. To that user, parse errors are not a normal thing; they're an exc=
eptional circumstance. If there's a parse error, this user wants to complet=
ely shut down all processing of this data, under the presumption that somet=
hing truly terrible has happened in the system. Perhaps to the point of rol=
ling back any changes made based on this data, since it must now be conside=
red suspect.
>=20
Here you=E2=80=99re dealing with a different case scenarios: program _bugs_=
.. It=E2=80=99s what asserts are for (but I don=E2=80=99t want to reopen the=
debate
about asserts please).
Anyway, the point is not that filesystem errors are different (=E2=80=9Csom=
ething rare=E2=80=9D as you say). It=E2=80=99s that _IO_ is different. What=
functional
languages have teached us is that everything we do can be effectively separ=
ated into two realms: pure code and IO code.=20
Since we=E2=80=99re talking about C++, please understand that by =E2=80=9Cp=
ure=E2=80=9D I don=E2=80=99t mean =E2=80=9Cstateless=E2=80=9D. I simply mea=
n code that does not do IO.
IO is not only filesystem of course, but also everything else that involves=
the environment: network, inter-thread communication,
system calls of any form, etc=E2=80=A6 The important thing about this separ=
ation is that if you remove all those factors, your code is=20
_truly deterministic_. If you pass =E2=80=9Chello=E2=80=9D to parse_int you=
will _always_ get an error, and if you pass it =E2=80=9C42=E2=80=9D you wi=
ll _always_ get a result,
no matter what (for a reasonable implementation of parse_int). This is wher=
e I=E2=80=99d use expected.
> If this code were using `file_parse_integer`, it would react to a parse e=
rror in the exact same way it reacts to a filesystem error: halt the proces=
s at its source, undo anything that was done, and resume normal functionali=
ty.
>=20
> Is it reasonable for this user to have to manually return `expected` obje=
cts or failure error codes, just to be able to get the error where it needs=
to go?
>=20
I=E2=80=99ll say yes, it is reasonable, once we have a syntax to deal with =
it.
That syntax will hopefully be the one introduced by the =E2=80=9Cawait 2.0=
=E2=80=9D proposal
(and the required adaptation of the std::expected interface)
expected<int, parse_error> parse_int(std::string s);
expected<int, parse_error> file_parse_int(std::istream &s) {
auto string =3D get_nonblanks_string(s);=20
yield parse_int(string);
}
See? no clutter at all. A =E2=80=98yield=E2=80=99 instead of a return.
Please, please, please: don=E2=80=99t waste the expertise from decades of r=
esearch.
This is the kind of monadic programming that functional languages are emplo=
ying
since _decades_. The C++ standard committee is not facing a new, never seen=
problem.
> So in one case, we have a user who has a genuine reason to want file read=
ing errors to be exceptions, but would probably want actual parse errors to=
be `expected`s. While the other use wants both of them to be exceptions.
>=20
> You might say that it's fine, because if you get the `expected` value wit=
hout checking it, an exception will be thrown if it isn't there. And that i=
s true.
>=20
> But let us consider the nature of that exception.
>=20
> The most recent proposal of `expected` <http://www.open-std.org/JTC1/SC22=
/WG21/docs/papers/2014/n4109.pdf> basically has two variations: one for arb=
itrary error code objects and one for `exception_ptr`. In the latter case, =
the `exception_ptr` is thrown as that exception. In the former case, a temp=
late class is thrown, based on the type for the error code used by the `exp=
ected`. Now, std::error_condition can do quite a bit of stuff, based on the=
base `std::error_category` class it uses.
>=20
> However, everything that `error_condition` can do is based purely on the =
type of `error_category` it uses and an integer. Now, consider parsing inte=
gers. If a parse error occurs, the parsing system knows a lot of very usefu=
l information about it. It knows how many characters it successfully read. =
It knows exactly which character caused that error. And so forth.
>=20
> All of that information is lost when you reduce the error to a number.
>=20
> Certainly, `expected` can store something more than an `error_condition` =
(basically, an integer and a pointer). But if you start throwing around an =
`expected<int, big_giant_object>`, that's a huge cost to be paid compared t=
o just an `int`. It's bad enough that `expected<int, error_condition>`, on =
64-bit builds, is approaching a 32-byte cache-line in size; to make the obj=
ect even bigger is crazy. And if you need to propagate that out of the loca=
l scope, that's a big object to be returning up the callstack.
>=20
If the error data is very large, _and_ you need to propagate it up very dee=
ply _and_ performance=20
of that piece of code is a measurable bottleneck, then you may consider ano=
ther way, but should
this be the use case of the _default_ way of handling errors in a parsing l=
ibrary? Also, I don=E2=80=99t
see very frequently a single function used as parsing routine if it tracks =
all that state:
you=E2=80=99ll probably have a parser object and you can extract informatio=
n about the failure from
the object later (and return std::optional<T> instead of expected in this c=
ase).
By the way, if you use exceptions to handle a frequent condition such as pa=
rse errors,
you=E2=80=99ll incur in a lot of overhead. Do you have evidence that repeat=
edly throwing exceptions
is faster than returning a simple object (even if big) on the stack? I don=
=E2=80=99t think so.
> For local error handling, providing little information is reasonable, bec=
ause local code actually knows the context of the error. It knows what the =
input string was, the range of characters passed to `parse_integer`. Also, =
the return value(s) from `parse_integer` may include an offset to the parse=
d character, in some form.
>=20
> However, if an error needs to be propagated, simply inducing `expected` t=
o throw an exception via `.value()` is... rather useless when needing to ac=
tually report a problem. Oh sure, you can use `error_condition::message` to=
be told something about why the text didn't parse. But you know nothing ab=
out where this happened; that information was lost when the local scope ret=
urned the error code. You lose lots of very useful knowledge.
>=20
> By contrast, a `parse_integer` that natively fires off an exception can e=
ncapsulate useful information. It can say exactly where this error took pla=
ce in the given string. It can even store the given string in the exception=
, as reference. And so forth. Information that would have been lost to the =
local scope can now be granted to a higher scope.
>=20
> This was a problem (one of many) with a suggestion that was made in anoth=
er thread to have the FileSystem TS do away with exceptions entirely, relyi=
ng solely on `expected` for error handling <https://groups.google.com/a/iso=
cpp.org/d/msg/std-proposals/4MErTLraVDg/fK9pPtRgXRAJ>. The `filesystem_erro=
r` class is quite rich in information as to exactly where a problem happene=
d, able to store and return entire `path` objects that represent parameters=
to various error-generating functions. For local error resolving, this see=
ms like overkill. But for handling errors at a higher level? This is exactl=
y the kind of information that would be lost and can be critical for findin=
g out where a problem is.
>=20
That=E2=80=99s a good point.
Indeed, I don=E2=80=99t agree with the proposal of changing the Filesystem =
TS to use expected, for the reasons outlined above about IO failures.
> Consider the prior discussed case of a `parse_integer` function, where a =
parse error represents a fundamental failure of the entire process of parsi=
ng this data, causing a rollback of changes made based on it. If you need t=
o log information based on this parse error, the exception case can give yo=
u something that's actually useful. The `expected` case simply says, "Found=
a letter instead of a number".
>=20
> Now, you could say that all `parse_integer` could store would be informat=
ion that's locally available: the string parameter. It wouldn't know how ma=
ny strings had already been processed or anything. And that is true; to get=
more information, you would need to do some exception translation, using s=
pecific knowledge at each layer to add new information.
>=20
> In that case, you have some local pre-processing of error information, ma=
ssaging it into the most useful form for consumption. And this is starting =
to resemble the `expected` case, where every layer between the erroring fun=
ction and the handler must know about these errors and propagate them expli=
citly in code. However, this way, you get to use an actual object, rather t=
han having to fit things into an `error_condition`. Yes, `expected` could u=
se any object; however, as previously discussed, if multiple paths of code =
need to propagate multiple errors up the same function, `error_condition` i=
s pretty much the only sane way to go. Unless you like sorting through `var=
iants`.
>=20
The =E2=80=9Cmultiple sources of errors=E2=80=9D problem could be handled b=
y suitable combination functions.
> The exception case is so much cleaner, even with having to do translation=
at various layers. Only layers that actually do translation need to be inv=
olved in that process; otherwise, the code is clean.
>=20
That if you assume _all_ the possible exceptions are correctly handled (and=
remember that
in C++ they=E2=80=99re not stated anywhere in the type system). If not, wha=
t you see as
=E2=80=9Cclean=E2=80=9D code, I see as _buggy_ code.
> And then there are things that `expected` flat-out cannot handle or handl=
es very poorly.
>=20
> The first is any function that doesn't return a value. Oh yes, `expected<=
void, ec>` exists. But it would be rather... foolish to expect everyone to =
do that. Uniformly.
>=20
> The same applies to any function that returns a value that most users wil=
l drop on the floor. `filesystem::create_directory` is a good example. Most=
people will just assume it succeeded. But only in the exception case will =
they be forced to confront the possibility of failure.
>=20
> To be fair to `expected`, the latter two can be helped via external tools=
.. It would be possible, particularly with Clang, to write a tool that scans=
for `expected` return values that are discarded.
>=20
> The more extreme case is object construction, for which the C++ standard =
has no solution other than exceptions. Options like `expected(in_place_t)` =
don't really work. You lose "uniform" initialization syntax, as you can't a=
ccess the initializer_list constructor with {}. It's a nice try, and is nec=
essary for initializing immobile types. But it doesn't work nearly as well =
as a straight constructor. And most importantly of all, it doesn't actually=
capture any exceptions thrown by `T`'s constructor.
>=20
I see exceptions in constructors a bit suspicious, though.
I agree they have to handled someway, of course.
>=20
> That all brings me to a number of conclusions:
>=20
> 1) Exceptions work best in non-local error handling contexts. Local error=
handling best works via `expected`, except where `expected` cannot be used=
or is poor at the job.
>=20
> 2) The difference between local and non-local handling cannot be known to=
the library. It may guess and hope, but there are usually legitimate cases=
where a user might handle errors one way or the other.
>=20
> 3) Where possible, allow the user to decide whether errors are handled lo=
cally or not. As such, functions that error should have two versions: one t=
hat throws and one that uses `expected`.
>=20
Agreed.
Bye,
Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_B08DE8F2-CA27-4D26-9B60-9BA06516C3CE
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">Il giorno 03/giu/201=
5, alle ore 07:09, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com" c=
lass=3D"">jmckesson@gmail.com</a>> ha scritto:</div><br class=3D"Apple-i=
nterchange-newline"><div class=3D""><div dir=3D"ltr" class=3D"">After readi=
ng through various people's ideas about how to go about <a href=3D"https://=
groups.google.com/a/isocpp.org/d/msg/std-proposals/MJIRnrc7vbo/jGO0zjXQrEYJ=
" class=3D"">reporting errors from number parsing systems</a>, as well as w=
riting a <a href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-propos=
als/G1YheYoGznw/7AuxvrJhv6gJ" class=3D"">preliminary document on the variet=
y of error reporting mechanisms</a> in applications and libraries at presen=
t, I've come to some thoughts and conclusions on how error reporting and re=
solution ought to be handled.<br class=3D""><br class=3D"">When I analyzed =
the various error reporting mechanisms, I did so along three independent ax=
es: local error resolution, non-local error resolution, and local error ign=
oring. What I came to realize is that, generally speaking, in the event of =
an error condition, code does one of the following: the error is resolved b=
y the code that directly generated it; the error is resolved by someone els=
e; or the program forges ahead, blissfully unaware of an error. That may so=
und obvious, but it's an important point.<br class=3D""><br class=3D""></di=
v></div></blockquote><div><br class=3D""></div><div>Hi. Yes it is an import=
ant point indeed. Errors should not go =E2=80=9Cblissfully=E2=80=9D ignored=
, though.</div><div>There must be a very good motivation to ignore a possib=
le source of exceptions</div><div>(see out of memory exceptions), and in my=
opinion the language/library should enforce</div><div>the user to explicit=
ly choose to ignore errors.</div><div><br class=3D""></div><div>This is als=
o the main fundamental difference between exceptions and expected: the defa=
ult is to ignore the error in the first case,</div><div>to handle it in the=
second. </div><br class=3D""><blockquote type=3D"cite" class=3D""><di=
v class=3D""><div dir=3D"ltr" class=3D"">The thing that set my mind to this=
was with the whole number parsing thing. In there, people made a strong ca=
se for `expected`, but these cases were always in the context of local erro=
r resolution. The function that was directly calling the `parse_integer` fu=
nction would be resolving the ensuing error.<br class=3D""><br class=3D"">T=
he argument being that parse errors are expected; they're entirely natural.=
So it's expected that the local caller will field such errors, and if the =
caller doesn't, then the local caller has decided effectively not to care. =
In such an event, throwing an exception is warranted. So `expected` seems q=
uite ideal in such circumstances; if you try to fetch the value without che=
cking that it's there, the system will throw a wrapped error code.<br class=
=3D""><br class=3D""></div></div></blockquote><div><br class=3D""></div><di=
v>Indeed.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div cla=
ss=3D""><div dir=3D"ltr" class=3D"">This seems ideal, but there are many fl=
aws with such an approach. For example, this approach assumes that the loca=
l caller function is actually capable of resolving this kind of error. The =
farther up the call graph one has to search to resolve an `expected` error,=
the more difficult it gets to get the `expected` error where it needs to g=
o.<br class=3D""><br class=3D""></div></div></blockquote><div><br class=3D"=
"></div><div>You=E2=80=99re not =E2=80=9Cassuming=E2=80=9D the caller is ca=
pable of resolving the error: you=E2=80=99re _enforcing_ the caller to thin=
k about the error,</div><div>and _explicitly_ chose to ignore it or propaga=
te it up if it cannot handle it.</div><br class=3D""><blockquote type=3D"ci=
te" class=3D""><div class=3D""><div dir=3D"ltr" class=3D"">As an example, c=
onsider `parse_integer`. If `parse_integer` has no knowledge of filesystem =
IO, then it is reasonable for a user to write a function that can take a fi=
le IO object and parse integers from it. Call this `file_parse_integer`; it=
reads some number of non-space characters from a file stream, passes the s=
tring to `parse_integer` and then returns... what?<br class=3D""><br class=
=3D"">It cannot return `expected<int, parse_error>`. Why? Because `fi=
le_parse_integer` can now fail for two <i class=3D"">separate</i> reasons: =
a failure to parse the characters, and a failure to <i class=3D"">read the =
characters from the file stream</i>. The only legitimate thing that `file_p=
arse_integer` can do is return both possibilities: `expected<int, varian=
t<parse_error, file_error>>`. If both the file reading error and t=
he parse error use `std::error_condition`, then at least the variant can be=
avoided. But regardless of how the error is returned, the direct caller is=
required to field all of the cases. But not just all of the parse error ca=
ses; he must field all of the file reading cases too.<br class=3D""><br cla=
ss=3D""></div></div></blockquote><div>This point ignores the distinction yo=
u made at the beginning: the parse error is a natural condition, the IO err=
or is not (in general).</div><div>So in my opinion such a case should be ha=
ndled by returning an expected<int, parse_error> _and_ throw an excep=
tion in case</div><div>of IO errors. </div><div><br class=3D""></div><=
div>That is exactly the distinction made by functional languages such as Ha=
skell, which as you may know make a strong distinction </div><div>betw=
een pure computations (parsing a file) and IO actions (reading the file fro=
m the stream). The hybrid interface I proposed above</div><div>mimics exact=
ly this distinction. You=E2=80=99re explicitly dealing with the result of t=
he =E2=80=9Cpure=E2=80=9D part of your code while using an out-of-band</div=
><div>channel to signal IO exceptions.</div><div><br class=3D""></div><div>=
More on that a few points later.</div><br class=3D""><blockquote type=3D"ci=
te" class=3D""><div class=3D""><div dir=3D"ltr" class=3D"">One might say th=
at this is still true even if using exceptions, but I contest this for one =
very important reason: file reading errors usually represent a fundamentall=
y different kind of problem than parsing errors. If an integer parse fails,=
that could be reasonably expected by the user and handled locally. If a fi=
le fails to read at all, this is not a problem that someone who's expecting=
to read an integer can resolve; it can only be effectively resolved by hig=
her level code. The system that began this entire "parse stuff from a file"=
needs to be notified that it failed. How many levels high is that system? =
Who knows.<br class=3D""><br class=3D""></div></div></blockquote><div>That=
=E2=80=99s why I agree you should use exceptions for IO-related failures.</=
div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><di=
v dir=3D"ltr" class=3D"">Is it reasonable for callers of `file_parse_intege=
r` to have to manually propagate that error all the way back?<br class=3D""=
><br class=3D""></div></div></blockquote><blockquote type=3D"cite" class=3D=
""><div class=3D""><div dir=3D"ltr" class=3D"">Next, one might say that thi=
s is a special case, that filesystem errors are always a different kind of =
thing, something which is rare and thus clearly ought to be handled by exce=
ptions. That is not an unreasonable argument. However, there are times when=
parse errors can logically be treated in the same light. This would be in =
a file format that you the programmer have fundamental control over, who's =
contents are generated by internal code, not the user. To that user, parse =
errors are not a normal thing; they're an exceptional circumstance. If ther=
e's a parse error, this user wants to completely shut down all processing o=
f this data, under the presumption that something truly terrible has happen=
ed in the system. Perhaps to the point of rolling back any changes made bas=
ed on this data, since it must now be considered suspect.<br class=3D""><br=
class=3D""></div></div></blockquote><div><br class=3D""></div><div>Here yo=
u=E2=80=99re dealing with a different case scenarios: program _bugs_. It=E2=
=80=99s what asserts are for (but I don=E2=80=99t want to reopen the debate=
</div><div>about asserts please).</div><div>Anyway, the point is not that f=
ilesystem errors are different (=E2=80=9Csomething rare=E2=80=9D as you say=
). It=E2=80=99s that _IO_ is different. What functional</div><div>languages=
have teached us is that everything we do can be effectively separated into=
two realms: pure code and IO code. </div><div>Since we=E2=80=99re tal=
king about C++, please understand that by =E2=80=9Cpure=E2=80=9D I don=E2=
=80=99t mean =E2=80=9Cstateless=E2=80=9D. I simply mean code that does not =
do IO.</div><div>IO is not only filesystem of course, but also everything e=
lse that involves the environment: network, inter-thread communication,</di=
v><div>system calls of any form, etc=E2=80=A6 The important thing about thi=
s separation is that if you remove all those factors, your code is </d=
iv><div>_truly deterministic_. If you pass =E2=80=9Chello=E2=80=9D to parse=
_int you will _always_ get an error, and if you pass it =E2=80=9C42=E2=80=
=9D you will _always_ get a result,</div><div>no matter what (for a reasona=
ble implementation of parse_int). This is where I=E2=80=99d use expected.</=
div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><di=
v dir=3D"ltr" class=3D"">If this code were using `file_parse_integer`, it w=
ould react to a parse error in the exact same way it reacts to a filesystem=
error: halt the process at its source, undo anything that was done, and re=
sume normal functionality.<br class=3D""><br class=3D"">Is it reasonable fo=
r this user to have to manually return `expected` objects or failure error =
codes, just to be able to get the error where it needs to go?<br class=3D""=
><br class=3D""></div></div></blockquote><div><br class=3D""></div><div>I=
=E2=80=99ll say yes, it is reasonable, once we have a syntax to deal with i=
t.</div><div>That syntax will hopefully be the one introduced by the =E2=80=
=9Cawait 2.0=E2=80=9D proposal</div><div>(and the required adaptation of th=
e std::expected interface)</div><div><br class=3D""></div><div>expected<=
int, parse_error> parse_int(std::string s);</div><div><br class=3D""></d=
iv><div>expected<int, parse_error> file_parse_int(std::istream &s=
) {</div><div> auto string =3D get_nonblanks_string(s); </=
div><div><br class=3D""></div><div> yield parse_int(string);</d=
iv><div>}</div><div><br class=3D""></div><div>See? no clutter at all. A =E2=
=80=98yield=E2=80=99 instead of a return.</div><div><br class=3D""></div><d=
iv>Please, please, please: don=E2=80=99t waste the expertise from decades o=
f research.</div><div>This is the kind of monadic programming that function=
al languages are employing</div><div>since _decades_. The C++ standard comm=
ittee is not facing a new, never seen problem.</div></div><div><br class=3D=
""><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" cl=
ass=3D"">So in one case, we have a user who has a genuine reason to want fi=
le reading errors to be exceptions, but would probably want actual parse er=
rors to be `expected`s. While the other use wants both of them to be except=
ions.<br class=3D""><br class=3D"">You might say that it's fine, because if=
you get the `expected` value without checking it, an exception will be thr=
own if it isn't there. And that is true.<br class=3D""><br class=3D"">But l=
et us consider the nature of that exception.<br class=3D""><br class=3D"">T=
he <a href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4109=
..pdf" class=3D"">most recent proposal of `expected`</a> basically has two v=
ariations: one for arbitrary error code objects and one for `exception_ptr`=
.. In the latter case, the `exception_ptr` is thrown as that exception. In t=
he former case, a template class is thrown, based on the type for the error=
code used by the `expected`. Now, std::error_condition can do quite a bit =
of stuff, based on the base `std::error_category` class it uses.<br class=
=3D""><br class=3D"">However, everything that `error_condition` can do is b=
ased purely on the type of `error_category` it uses and an integer. Now, co=
nsider parsing integers. If a parse error occurs, the parsing system knows =
a lot of very useful information about it. It knows how many characters it =
successfully read. It knows exactly which character caused that error. And =
so forth.<br class=3D""><br class=3D"">All of that information is <i class=
=3D"">lost</i> when you reduce the error to a number.<br class=3D""><br cla=
ss=3D""></div></div></blockquote><blockquote type=3D"cite" class=3D""><div =
class=3D""><div dir=3D"ltr" class=3D"">Certainly, `expected` can store some=
thing more than an=20
`error_condition` (basically, an integer and a pointer). But if you=20
start throwing around an `expected<int, big_giant_object>`, that's
a huge cost to be paid compared to just an `int`. It's bad enough that `ex=
pected<int, error_condition>`, on 64-bit builds, is approaching a 32-=
byte cache-line in size; to make the object even bigger is crazy. And if yo=
u need to propagate that out of the=20
local scope, that's a big object to be returning up the callstack.<br class=
=3D""><br class=3D""></div></div></blockquote><div><br class=3D""></div><di=
v>If the error data is very large, _and_ you need to propagate it up very d=
eeply _and_ performance </div><div>of that piece of code is a measurab=
le bottleneck, then you may consider another way, but should</div><div>this=
be the use case of the _default_ way of handling errors in a parsing libra=
ry? Also, I don=E2=80=99t</div><div>see very frequently a single function u=
sed as parsing routine if it tracks all that state:</div><div>you=E2=80=99l=
l probably have a parser object and you can extract information about the f=
ailure from</div><div>the object later (and return std::optional<T> i=
nstead of expected in this case).</div><div><br class=3D""></div>By the way=
, if you use exceptions to handle a frequent condition such as parse errors=
,</div><div>you=E2=80=99ll incur in a lot of overhead. Do you have evidence=
that repeatedly throwing exceptions</div><div>is faster than returning a s=
imple object (even if big) on the stack? I don=E2=80=99t think so.</div><di=
v><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div =
dir=3D"ltr" class=3D"">For local error handling, providing little informati=
on is reasonable, because local code actually knows the context of the erro=
r. It knows what the input string was, the range of characters passed to `p=
arse_integer`. Also, the return value(s) from `parse_integer` may include a=
n offset to the parsed character, in some form.<br class=3D""><br class=3D"=
">However, if an error needs to be propagated, simply inducing `expected` t=
o throw an exception via `.value()` is... rather useless when needing to ac=
tually report a problem. Oh sure, you can use `error_condition::message` to=
be told something about why the text didn't parse. But you know <i class=
=3D"">nothing</i> about where this happened; that information was lost when=
the local scope returned the error code. You lose lots of very useful know=
ledge.<br class=3D""><br class=3D"">By contrast, a `parse_integer` that nat=
ively fires off an exception can encapsulate useful information. It can say=
exactly where this error took place in the given string. It can even store=
the given string in the exception, as reference. And so forth. Information=
that would have been lost to the local scope can now be granted to a highe=
r scope.<br class=3D""><br class=3D"">This was a problem (one of many) with=
a suggestion that was made in another thread to have <a href=3D"https://gr=
oups.google.com/a/isocpp.org/d/msg/std-proposals/4MErTLraVDg/fK9pPtRgXRAJ" =
class=3D"">the FileSystem TS do away with exceptions <i class=3D"">entirely=
</i>, relying solely on `expected` for error handling</a>. The `filesystem_=
error` class is quite rich in information as to exactly where a problem hap=
pened, able to store and return entire `path` objects that represent parame=
ters to various error-generating functions. For local error resolving, this=
seems like overkill. But for handling errors at a higher level? This is ex=
actly the kind of information that would be lost and can be critical for fi=
nding out where a problem is.<br class=3D""><br class=3D""></div></div></bl=
ockquote><div><br class=3D""></div><div>That=E2=80=99s a good point.</div><=
div>Indeed, I don=E2=80=99t agree with the proposal of changing the Filesys=
tem TS to use expected, for the reasons outlined above about IO failures.</=
div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><di=
v dir=3D"ltr" class=3D"">Consider the prior discussed case of a `parse_inte=
ger` function, where a parse error represents a fundamental failure of the =
entire process of parsing this data, causing a rollback of changes made bas=
ed on it. If you need to log information based on this parse error, the exc=
eption case can give you something that's actually useful. The `expected` c=
ase simply says, "Found a letter instead of a number".<br class=3D""><br cl=
ass=3D"">Now, you could say that all `parse_integer` could store would be i=
nformation that's locally available: the string parameter. It wouldn't know=
how many strings had already been processed or anything. And that is true;=
to get more information, you would need to do some exception translation, =
using specific knowledge at each layer to add new information.<br class=3D"=
"><br class=3D"">In that case, you have some local pre-processing of error =
information, massaging it into the most useful form for consumption. And th=
is is starting to resemble the `expected` case, where every layer between t=
he erroring function and the handler must know about these errors and propa=
gate them explicitly in code. However, this way, you get to use an actual o=
bject, rather than having to fit things into an `error_condition`. Yes, `ex=
pected` could use any object; however, as previously discussed, if multiple=
paths of code need to propagate multiple errors up the same function, `err=
or_condition` is pretty much the only sane way to go. Unless you like sorti=
ng through `variants`.<br class=3D""><br class=3D""></div></div></blockquot=
e><div>The =E2=80=9Cmultiple sources of errors=E2=80=9D problem could be ha=
ndled by suitable combination functions.</div><div><br class=3D""></div><br=
class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div dir=
=3D"ltr" class=3D"">The exception case is so much cleaner, even with having=
to do translation at various layers. Only layers that actually do translat=
ion need to be involved in that process; otherwise, the code is clean.<br c=
lass=3D""><br class=3D""></div></div></blockquote><div><br class=3D""></div=
><div>That if you assume _all_ the possible exceptions are correctly handle=
d (and remember that</div><div>in C++ they=E2=80=99re not stated anywhere i=
n the type system). If not, what you see as</div><div>=E2=80=9Cclean=E2=80=
=9D code, I see as _buggy_ code.</div><br class=3D""><blockquote type=3D"ci=
te" class=3D""><div class=3D""><div dir=3D"ltr" class=3D"">And then there a=
re things that `expected` flat-out cannot handle or handles very poorly.<br=
class=3D""><br class=3D"">The first is any function that doesn't return a =
value. Oh yes, `expected<void, ec>` exists. But it would be rather...=
foolish to expect everyone to do that. Uniformly.<br class=3D""><br class=
=3D"">The same applies to any function that returns a value that most users=
will drop on the floor. `filesystem::create_directory` is a good example. =
Most people will just assume it succeeded. But only in the exception case w=
ill they be forced to confront the possibility of failure.<br class=3D""><b=
r class=3D"">To be fair to `expected`, the latter two can be helped via ext=
ernal tools. It would be possible, particularly with Clang, to write a tool=
that scans for `expected` return values that are discarded.<br class=3D"">=
<br class=3D"">The more extreme case is object construction, for which the =
C++ standard has no solution other than exceptions. Options like `expected(=
in_place_t)` don't really work. You lose "uniform" initialization syntax, a=
s you can't access the initializer_list constructor with {}. It's a nice tr=
y, and is necessary for initializing immobile types. But it doesn't work ne=
arly as well as a straight constructor. And most importantly of all, it doe=
sn't actually capture any exceptions thrown by `T`'s constructor.<br class=
=3D""><br class=3D""></div></div></blockquote><div><br class=3D""></div><di=
v>I see exceptions in constructors a bit suspicious, though.</div><div>I ag=
ree they have to handled someway, of course.</div><br class=3D""><blockquot=
e type=3D"cite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><br =
class=3D"">That all brings me to a number of conclusions:<br class=3D""><br=
class=3D"">1) Exceptions work best in non-local error handling contexts. L=
ocal error handling best works via `expected`, except where `expected` cann=
ot be used or is poor at the job.<br class=3D""><br class=3D"">2) The diffe=
rence between local and non-local handling <i class=3D"">cannot be known to=
the library</i>. It may guess and hope, but there are usually legitimate c=
ases where a user might handle errors one way or the other.<br class=3D""><=
br class=3D"">3) Where possible, allow the user to decide whether errors ar=
e handled locally or not. As such, functions that error should have two ver=
sions: one that throws and one that uses `expected`.<br class=3D""></div><d=
iv class=3D""><br class=3D"webkit-block-placeholder"></div></div></blockquo=
te><div><br class=3D""></div><div>Agreed.</div><div><br class=3D""></div><d=
iv><br class=3D""></div><div>Bye,</div><div>Nicola</div></div></body></html=
>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_B08DE8F2-CA27-4D26-9B60-9BA06516C3CE--
.
Author: Christopher <christopherhallock@gmail.com>
Date: Wed, 3 Jun 2015 07:57:51 -0700 (PDT)
Raw View
------=_Part_168_553710458.1433343471487
Content-Type: multipart/alternative;
boundary="----=_Part_169_1165025155.1433343471487"
------=_Part_169_1165025155.1433343471487
Content-Type: text/plain; charset=UTF-8
Would motivation for 'expected' evaporate if there were no performance
issues over throwing exceptions frequently?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_169_1165025155.1433343471487
Content-Type: text/html; charset=UTF-8
<div dir="ltr">Would motivation for 'expected' evaporate if there were no performance issues over throwing exceptions frequently?<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
------=_Part_169_1165025155.1433343471487--
------=_Part_168_553710458.1433343471487--
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Wed, 3 Jun 2015 17:41:44 +0200
Raw View
> Il giorno 03/giu/2015, alle ore 16:57, Christopher <christopherhallock@gm=
ail.com> ha scritto:
>=20
> Would motivation for 'expected' evaporate if there were no performance is=
sues over throwing exceptions frequently?
>=20
No, it won=E2=80=99t.
Expected have the feature of explicitly documenting _in the type system_ th=
at
the function is partial and could happen that it cannot return the promised=
result
(same reasoning with std::optional, but with the ability to say what went w=
rong).
That _enforces_ the caller to think about the handling of the error, even i=
f it means
to just ignore it.
Bye,
Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 3 Jun 2015 19:31:46 +0300
Raw View
On 3 June 2015 at 18:41, Nicola Gigante <nicola.gigante@gmail.com> wrote:
>
>> Il giorno 03/giu/2015, alle ore 16:57, Christopher <christopherhallock@g=
mail.com> ha scritto:
>>
>> Would motivation for 'expected' evaporate if there were no performance i=
ssues over throwing exceptions frequently?
>>
>
> No, it won=E2=80=99t.
>
> Expected have the feature of explicitly documenting _in the type system_ =
that
> the function is partial and could happen that it cannot return the promis=
ed result
> (same reasoning with std::optional, but with the ability to say what went=
wrong).
>
> That _enforces_ the caller to think about the handling of the error, even=
if it means
> to just ignore it.
Also, no, because expected allows collecting results into a container
without writing
try-blocks, when the partial results return expected. It's not just a
performance tool, and
in many cases performance has rather little to do with how and why it's use=
d.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Wed, 3 Jun 2015 09:43:06 -0700 (PDT)
Raw View
------=_Part_7138_874380709.1433349786990
Content-Type: multipart/alternative;
boundary="----=_Part_7139_485979742.1433349786990"
------=_Part_7139_485979742.1433349786990
Content-Type: text/plain; charset=UTF-8
If we keep framing it in what C++ was able to do in 1998, then the options
always all come out looking bad.
Research has gone on in error-handling mechanisms since C++ first arose.
There have been more options since before C++ even existed.
One could overcome most (all, I think) of the problems of exceptions and
today's expected by using the following further improvements. The following
are partially implementable in C++ today with a some templates, a few
macros, and a couple big limitations/restrictions, but some of the more
interesting bits are not super feasible in C++ today without some language
evolution:
- expected<> cannot be unwrapped without checking for errors:
..value() or the like would simply not exist. Code would be required to work
as follows:
expected.when {
case good (auto value) { use value; }
case failed (auto error) { handle error; }
}
This is what you see in most functional languages.
Note that you can almost emulate this today by using lambdas and a
..when(good_callback, error_callback) interface:
expected.when(
[](auto& good) { use value; },
[](auto& error) { handle_error });
The problem there is that you can't return from the callbacks usefully,
which poses severe usability issues for many common cases (especially the
error case where your preferred action may be to cease further execution of
the enclosing function).
This avoid accidental use-before-check, but does not avoid accidental
unused-and-unchecked (you could just ignore your expected values).
- A further extension of this then is the unwrap-if-you-can operator,
letting you write convenient shorthand like:
result = expected?.foo?.bar();
// translates to
result = bool(expected) ? bool(expected->foo) ? expected->foo->bar() :
expected->foo.error() : expected.error();
The nice thing about this is that can extend to many other useful contexts.
Consider optional:
optional<my_type> a = ...;
auto b = my_type?.foo(); // b will be an optional of whatever foo()
returns, and may either be engaged or nullopt.
And the same for other types like variant, home-grown error wrappers in
existing libraries and interfaces, iterators/cursors that know if they're
valid or not, and so on.
Would probably want ?., ?->, and unary ?* to cover all three major cases of
unwrapping today. (Syntax is just a strawman, of course.)
- expected can contain more than one type of error:
expected<int, parse_error, io_error>
Solves one of the problems you outlined in the first post. this is possible
today of course without new syntax or features.
The automatic unwrapping code above automatically folds errors into a
single union of all error types that may occur in the expression.
This support also basically turns expected into a variant of variant
(sorry) in which one of the cases is explicitly treated as the "good" case
and the others are all "error" cases. e.g., expected might even just become:
template <class V, class... E>
expected = variant<good<V>, fail<E...>>;
- expression-try integrated with expected and flow control
This allows code to more easily halt execution of the current context. So
you could write this:
expected<int, error> foo(int a) {
int b = a + try some_fallable_function();
return other_stuff(b);
}
and it becomes equivalent to:
expected<int, error> foo(int a) {
some_fallable_function().when {
case good (auto& tmp): {
int b = a + tmp;
return other_stuff(b); }
case error (auto& e): return e;
}
}
That is, it unwraps an expected if it's good, and otherwise immediately
returns the contained error otherwise.
I'm led to believe from the last thread that Gor's awaitable functions
proposal might allow the above, albeit with a somewhat surprising keyword
(await) in place of try.
- Existing exception-based code can be made to work with helpers
This would include a statement that does the equivalent of today's
try/catch but automatically returns the exception in the latter case.
Something like:
expected<int, error> foo() {
inline try {
return some_throwing_function();
}
}
This has the further advantage over today's exceptions that (a) changing
the signature of foo from one that does not fail to one that does forces
you to update and acknowledge the change in interface at call sites rather
than introducing silent bugs or completely unknown code flows; and (b)
fixes the problems of the failed throws approach by making the list of
possible errors part of the function signature, and in a way that does not
automatically require calling functions to adjust if they just pass the
error through thanks to auto-return-type-deduction and the above
try-expression syntax.
Likewise, code that unwraps an expected or throws the contained error
(which we have today) can work. I dislike this one because it makes it too
easy to accidentally throw an exception. I'd at least like this function to
be named appropriately, e.g. .value_or_throw() to avoid
accidental/incidental misuse.
This would work even better if all C++ functions where noexcept(true) by
default and noexcept(false) were the opt-in case, allowing the compiler to
make more intelligent choices for the programmer, but of course that's not
likely to ever become the case for C++ for back-compat reasons. :(
Note that the previous item's expression-try should not automatically catch
exceptions, as expression-try has to know the resulting type of its
expected<>, which is not possible with general exception catching in C++
(you can't even just wrap std::exception for noexcept(false) functions
without causing a ton of issues). Conversion from C++ exceptions to
expected<> must be more explicitly opted-in to by the programmer to avoid
type system limitations and performance issues.
Note that Rust is exploring a similar-ish route with expression-try and
unwrapping. They have less need for such a mechanism because they're
already a functional-paradigm-ready language with first-class sum types,
pattern matching, and no existing misdesigned exception mechanism to work
around; their RFCs on expression-try are more about ease-of-use/ergonomics
than it is for fixing a major failing of the language like it would be for
C++. https://github.com/rust-lang/rfcs/pull/243 is just one of said RFCs,
for your edification.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_7139_485979742.1433349786990
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">If we keep framing it in what C++ was able to do in 1998, =
then the options always all come out looking bad.<div><br></div><div>Resear=
ch has gone on in error-handling mechanisms since C++ first arose. There ha=
ve been more options since before C++ even existed.</div><div><br></div><di=
v>One could overcome most (all, I think) of the problems of exceptions and =
today's expected by using the following further improvements. The following=
are partially implementable in C++ today with a some templates, a few macr=
os, and a couple big limitations/restrictions, but some of the more interes=
ting bits are not super feasible in C++ today without some language evoluti=
on:</div><div><br></div><div>- expected<> cannot be unwrapped without=
checking for errors:</div><div><br></div><div>.value() or the like would s=
imply not exist. Code would be required to work as follows:</div><div><br><=
/div><div> expected.when {</div><div> case good (auto va=
lue) { use value; }</div><div> case failed (auto error) { hand=
le error; }</div><div> }</div><div><br></div><div>This is what you se=
e in most functional languages.</div><div><br></div><div>Note that you can =
almost emulate this today by using lambdas and a .when(good_callback, error=
_callback) interface:</div><div><br></div><div> expected.when(</div><=
div> [](auto& good) { use value; },</div><div>  =
; [](auto& error) { handle_error });</div><div><br></div><div>The probl=
em there is that you can't return from the callbacks usefully, which poses =
severe usability issues for many common cases (especially the error case wh=
ere your preferred action may be to cease further execution of the enclosin=
g function).</div><div><br></div><div>This avoid accidental use-before-chec=
k, but does not avoid accidental unused-and-unchecked (you could just ignor=
e your expected values).</div><div><br></div><div>- A further extension of =
this then is the unwrap-if-you-can operator, letting you write convenient s=
horthand like:<br></div><div><br></div><div> result =3D expected?.foo=
?.bar();</div><div> // translates to</div><div> result =3D bool=
(expected) ? bool(expected->foo) ? expected->foo->bar() : expected=
->foo.error() : expected.error();</div><div><br></div><div>The nice thin=
g about this is that can extend to many other useful contexts. Consider opt=
ional:</div><div><br></div><div> optional<my_type> a =3D ...;</=
div><div><br></div><div> auto b =3D my_type?.foo(); // b will be an o=
ptional of whatever foo() returns, and may either be engaged or nullopt.</d=
iv><div><br></div><div>And the same for other types like variant, home-grow=
n error wrappers in existing libraries and interfaces, iterators/cursors th=
at know if they're valid or not, and so on.</div><div><br></div><div>Would =
probably want ?., ?->, and unary ?* to cover all three major cases of un=
wrapping today. (Syntax is just a strawman, of course.)</div><div><br></div=
><div>- expected can contain more than one type of error:</div><div><br></d=
iv><div>expected<int, parse_error, io_error></div><div><br></div><div=
>Solves one of the problems you outlined in the first post. this is possibl=
e today of course without new syntax or features.</div><div><br></div><div>=
The automatic unwrapping code above automatically folds errors into a singl=
e union of all error types that may occur in the expression.</div><div><br>=
</div><div>This support also basically turns expected into a variant of var=
iant (sorry) in which one of the cases is explicitly treated as the "good" =
case and the others are all "error" cases. e.g., expected might even just b=
ecome:</div><div><br></div><div> template <class V, class... E>=
</div><div> expected =3D variant<good<V>, fail<E...>&g=
t;;</div><div><br></div><div>- expression-try integrated with expected and =
flow control</div><div><br></div><div>This allows code to more easily halt =
execution of the current context. So you could write this:</div><div><br></=
div><div><div> expected<int, error> foo(int a) {</div><div>&nbs=
p; int b =3D a + try some_fallable_function();</div><div><br></div><=
div> return other_stuff(b);</div><div> }</div></div><div=
><br></div><div>and it becomes equivalent to:</div><div><br></div><div>&nbs=
p; expected<int, error> foo(int a) {</div><div> some_fal=
lable_function().when {</div><div> case good (auto&=
tmp): {<br></div><div> int b =3D a + tmp;</div>=
<div> return other_stuff(b); }</div><div> =
case error (auto& e): return e;</div><div> }=
</div><div> }<br></div><div><br></div><div>That is, it unwraps an exp=
ected if it's good, and otherwise immediately returns the contained error o=
therwise.</div><div><br></div><div>I'm led to believe from the last thread =
that Gor's awaitable functions proposal might allow the above, albeit with =
a somewhat surprising keyword (await) in place of try.</div><div><br></div>=
<div><br></div><div>- Existing exception-based code can be made to work wit=
h helpers</div><div><br></div><div>This would include a statement that does=
the equivalent of today's try/catch but automatically returns the exceptio=
n in the latter case. Something like:</div><div><br></div><div>expected<=
int, error> foo() {</div><div> inline try {</div><div>  =
; return some_throwing_function();</div><div> }</div><div>}</div><div=
><br></div><div>This has the further advantage over today's exceptions that=
(a) changing the signature of foo from one that does not fail to one that =
does forces you to update and acknowledge the change in interface at call s=
ites rather than introducing silent bugs or completely unknown code flows; =
and (b) fixes the problems of the failed throws approach by making the list=
of possible errors part of the function signature, and in a way that does =
not automatically require calling functions to adjust if they just pass the=
error through thanks to auto-return-type-deduction and the above try-expre=
ssion syntax.</div><div><br></div><div>Likewise, code that unwraps an expec=
ted or throws the contained error (which we have today) can work. I dislike=
this one because it makes it too easy to accidentally throw an exception. =
I'd at least like this function to be named appropriately, e.g. .value_or_t=
hrow() to avoid accidental/incidental misuse.</div><div><br></div><div>This=
would work even better if all C++ functions where noexcept(true) by defaul=
t and noexcept(false) were the opt-in case, allowing the compiler to make m=
ore intelligent choices for the programmer, but of course that's not likely=
to ever become the case for C++ for back-compat reasons. :(</div><div><br>=
</div><div>Note that the previous item's expression-try should not automati=
cally catch exceptions, as expression-try has to know the resulting type of=
its expected<>, which is not possible with general exception catchin=
g in C++ (you can't even just wrap std::exception for noexcept(false) funct=
ions without causing a ton of issues). Conversion from C++ exceptions to ex=
pected<> must be more explicitly opted-in to by the programmer to avo=
id type system limitations and performance issues.</div><div><br></div><div=
><br></div><div><br></div><div>Note that Rust is exploring a similar-ish ro=
ute with expression-try and unwrapping. They have less need for such a mech=
anism because they're already a functional-paradigm-ready language with fir=
st-class sum types, pattern matching, and no existing misdesigned exception=
mechanism to work around; their RFCs on expression-try are more about ease=
-of-use/ergonomics than it is for fixing a major failing of the language li=
ke it would be for C++. https://github.com/rust-lang/rfcs/pull/243 is just =
one of said RFCs, for your edification.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_7139_485979742.1433349786990--
------=_Part_7138_874380709.1433349786990--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 3 Jun 2015 19:47:14 +0300
Raw View
On 3 June 2015 at 19:43, Sean Middleditch <sean.middleditch@gmail.com> wrote:
> If we keep framing it in what C++ was able to do in 1998, then the options
> always all come out looking bad.
>
> Research has gone on in error-handling mechanisms since C++ first arose.
> There have been more options since before C++ even existed.
>
> One could overcome most (all, I think) of the problems of exceptions and
> today's expected by using the following further improvements. The following
What exactly are those "problems of expected"?
> are partially implementable in C++ today with a some templates, a few
> macros, and a couple big limitations/restrictions, but some of the more
> interesting bits are not super feasible in C++ today without some language
> evolution:
>
> - expected<> cannot be unwrapped without checking for errors:
>
> .value() or the like would simply not exist. Code would be required to work
> as follows:
>
> expected.when {
> case good (auto value) { use value; }
> case failed (auto error) { handle error; }
> }
>
> This is what you see in most functional languages.
I completely fail to see how enforcing that sort of use is an
improvement over anything.
> This avoid accidental use-before-check, but does not avoid accidental
> unused-and-unchecked (you could just ignore your expected values).
>
> - A further extension of this then is the unwrap-if-you-can operator,
> letting you write convenient shorthand like:
>
> result = expected?.foo?.bar();
> // translates to
> result = bool(expected) ? bool(expected->foo) ? expected->foo->bar() :
> expected->foo.error() : expected.error();
>
> The nice thing about this is that can extend to many other useful contexts.
> Consider optional:
>
> optional<my_type> a = ...;
>
> auto b = my_type?.foo(); // b will be an optional of whatever foo()
> returns, and may either be engaged or nullopt.
>
> And the same for other types like variant, home-grown error wrappers in
> existing libraries and interfaces, iterators/cursors that know if they're
> valid or not, and so on.
Like nullable types in e.g. C#? I have heard mixed reports about whether those
are a good idea.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Sean Middleditch <sean@middleditch.us>
Date: Wed, 3 Jun 2015 10:30:20 -0700
Raw View
On Wed, Jun 3, 2015 at 9:47 AM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 3 June 2015 at 19:43, Sean Middleditch <sean.middleditch@gmail.com> wrote:
>> If we keep framing it in what C++ was able to do in 1998, then the options
>> always all come out looking bad.
>>
>> Research has gone on in error-handling mechanisms since C++ first arose.
>> There have been more options since before C++ even existed.
>>
>> One could overcome most (all, I think) of the problems of exceptions and
>> today's expected by using the following further improvements. The following
>
> What exactly are those "problems of expected"?
It doesn't solve the "no exceptions" problem? You can trivially
accidentally do this:
expected<int, error> ex = failing_function();
int f = ex.value(); // forgot to check, so it throws anyway, or
you're ****d and get an assert or even UB if exceptions are disabled
>
>> are partially implementable in C++ today with a some templates, a few
>> macros, and a couple big limitations/restrictions, but some of the more
>> interesting bits are not super feasible in C++ today without some language
>> evolution:
>>
>> - expected<> cannot be unwrapped without checking for errors:
>>
>> .value() or the like would simply not exist. Code would be required to work
>> as follows:
>>
>> expected.when {
>> case good (auto value) { use value; }
>> case failed (auto error) { handle error; }
>> }
>>
>> This is what you see in most functional languages.
>
> I completely fail to see how enforcing that sort of use is an
> improvement over anything.
That's the underlying mechanism of pattern matching, upon which you
build the rest of the support.
You could just hard-code everything else to be a one-off feature of
expected, but that'd be pretty dumb, no?
>> And the same for other types like variant, home-grown error wrappers in
>> existing libraries and interfaces, iterators/cursors that know if they're
>> valid or not, and so on.
>
> Like nullable types in e.g. C#? I have heard mixed reports about whether those
> are a good idea.
Not quite, though there are certainly a lot of similarities.
The big difference is that nullable types in C# are a one-off feature
than implements optional<> types in a questionable way. The problem of
course is that nullable types in C# don't actually do any of the other
stuff I outlined here, so they're small steps up from C++'s potential
optional<> in syntactical terseness but nowhere near the Option Type
in Haskell, Scala, Rust, OCaml, ML, Swift, etc.
In any case, if we have optional, expected, variant, etc. then we've
already got all the problems of nullable types in C#. It would be
silly to add all the problems and then fail to add any of the
solutions to those problems :)
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/_wYdqbRBPho/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
Sean Middleditch
http://seanmiddleditch.com
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Wed, 03 Jun 2015 13:36:03 -0400
Raw View
On 2015-06-03 01:09, Nicol Bolas wrote:
> However, everything that `error_condition` can do is based purely on the
> type of `error_category` it uses and an integer. Now, consider parsing
> integers. If a parse error occurs, the parsing system knows a lot of very
> useful information about it. It knows how many characters it successfully
> read. It knows exactly which character caused that error. And so forth.
>
> All of that information is *lost* when you reduce the error to a number.
Actually, if the caller passed in an output parameter to receive the end
pointer (which would not be an unusual use case), the caller would still
be able to construct your better exception.
I'm not convinced this is an argument against 'expected', though it
sounds like a reasonable argument against 'expected<T, error_code>' in
some contexts that I think deserves consideration.
> But if you start throwing around an `expected<int, big_giant_object>`
If you're storing big_giant_object inline rather than as some sort of
smart pointer, you're doing it wrong :-). (And indeed, since you're
storing it *by value*, and one or the other is AFAIK required, in this
case it might make sense for expected itself to store big_giant_object
as a pointer, whose nullness or not indicates if it has an int or a
big_giant_object.)
> And then there are things that `expected` flat-out cannot handle or handles
> very poorly.
>
> The first is any function that doesn't return a value. Oh yes,
> `expected<void, ec>` exists. But it would be rather... foolish to expect
> everyone to do that. Uniformly.
>
> The same applies to any function that returns a value that most users will
> drop on the floor.
Neither of these are cases that 'expected' is meant to solve, and it's
clearly the wrong tool in both cases. These - especially the second -
are cases where you want a 'checked result' type if just throwing in the
first place is not an option.
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 3 Jun 2015 20:43:48 +0300
Raw View
On 3 June 2015 at 20:30, Sean Middleditch <sean@middleditch.us> wrote:
>> What exactly are those "problems of expected"?
>
> It doesn't solve the "no exceptions" problem? You can trivially
> accidentally do this:
>
> expected<int, error> ex = failing_function();
>
> int f = ex.value(); // forgot to check, so it throws anyway, or
> you're ****d and get an assert or even UB if exceptions are disabled
You can end up with the same problem regardless of how much pattern matching
you do, if you end up calling code that internally throws but doesn't
exit with an exception,
so I don't think that's a problem with expected.
>>> expected.when {
>>> case good (auto value) { use value; }
>>> case failed (auto error) { handle error; }
>>> }
>>>
>>> This is what you see in most functional languages.
>> I completely fail to see how enforcing that sort of use is an
>> improvement over anything.
> That's the underlying mechanism of pattern matching, upon which you
> build the rest of the support.
That's great, but I see no reason why expected shouldn't have a value(). If you
don't want to use such a function, don't use it.
> You could just hard-code everything else to be a one-off feature of
> expected, but that'd be pretty dumb, no?
I fail to see how expected::value() is "hard-coding 'everything else'"
into expected.
> In any case, if we have optional, expected, variant, etc. then we've
> already got all the problems of nullable types in C#. It would be
> silly to add all the problems and then fail to add any of the
> solutions to those problems :)
Except that we don't have all the problems, the problem we don't have is that
we don't have nullable types as a language facility.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Sean Middleditch <sean@middleditch.us>
Date: Wed, 3 Jun 2015 12:08:08 -0700
Raw View
On Wed, Jun 3, 2015 at 10:43 AM, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 3 June 2015 at 20:30, Sean Middleditch <sean@middleditch.us> wrote:
>>> What exactly are those "problems of expected"?
>>
>> It doesn't solve the "no exceptions" problem? You can trivially
>> accidentally do this:
>>
>> expected<int, error> ex = failing_function();
>>
>> int f = ex.value(); // forgot to check, so it throws anyway, or
>> you're ****d and get an assert or even UB if exceptions are disabled
>
> You can end up with the same problem regardless of how much pattern matching
> you do, if you end up calling code that internally throws but doesn't
> exit with an exception,
> so I don't think that's a problem with expected.
Perfect is the enemy of good. In this case, saying that you _can_
still get boned is irrelevant, because this is C++ with all of its
history and we're pretty much stuck with old mistakes forever. We can
do significantly better and reduce the common occurrences of mistakes
in new code even if we are literally incapable of every fixing ever
single problem.
This is hardly a new or novel pattern in any case. expected<> is a
neutered form of what's existed for decades outside of C++. Created in
such a neutered way only because of C++'s language deficiencies.
We're better off having it than not having it at all, certainly!
(again, perfect vs good) I use something like expected in projects
today, because of course it's better than the status quo.
It is however disingenuous to claim that since it's better than today
that we shouldn't strive for even better. expected<> today if it lands
is something I'd utterly deprecate and replace in any future project
that can rely on a more capable revision of C++.
And any discussion of expected<> without looking strongly into the
future is just people being lazy and developing an obsolete technology
out of ignorance rather than necessity (and necessity happens, e.g.
the need to ship C++17 without waiting 5+ years for language
evolution! I understand that).
> That's great, but I see no reason why expected shouldn't have a value(). If you
> don't want to use such a function, don't use it.
Out in the real world of everyday software developers, people pick the
paths of least resistance. If there's a .value(), it's going to be
used far more often than it should (if not on _your_ project, or even
on mine, certainly on thousands of others), mostly out of ignorance or
laziness.
The user can still _accidentally_ ignore the error condition; and
unlike with plain C return codes or even C++ exceptions, ignoring the
error condition in this case is _always_ UB (if exceptions are
disabled) or just pointless (if exceptions are enabled; why not just
throw in the first place?).
With expected<>, you've added a way for an API and a careful user to
avoid exceptions and still check errors. Great!
You haven't solved the incidental/accidental misuse problem at all, though.
I'm gathering the feeling from this and other conversations that we've
had that you may not feel that's a big issue. I will exceedingly
strongly disagree, if so. :)
> I fail to see how expected::value() is "hard-coding 'everything else'"
> into expected.
The "everything else" was the rest of my original email.
..value() is not a complete solution to the stated problem: people can
ignore the error condition! Intentionally _and_ accidentally! .value()
doesn't solve that problem. expected<> as it stands solves other
problems, certainly. That's good news.
But we can solve all those problems _and_ solve most of the rest of
the problems; just not if the debate is constantly framed in C++98
technology. In the sense that we probably want to ship something for
C++17, that's probably the best we can do. But then discussions keep
erupting about "return values vs exceptions" (and then lists of
possible error strategies like Nicol's which was constrained by the
technology of C++ today rather than being open to what could be if
people broadened their experience a bit).
And it's hardly like these things aren't (to an extent) already in the
works or being explored in C++ today:
- Bjarne and others are already exploring pattern matching in the
context of C++.
- Big software frameworks have had Result<T,Error> types for far
longer than expected<> has existed and also have explored all the
support utilities and macros to make such types easier to use
correctly.
- Custom TRY macros have existed since C's days which automatically
handle propagating errors from fallable expression-statements (though
they can't do the try-expression syntax or unwrapping operator; those
are currently impossible to even emulate in portable C++).
- Gor's awaitable work could even buy us try-expression syntax for free.
The confluence of all these can result in something better than
expected<>. Exploring a few more options (e.g. unwrapping operators)
that wide software industry experience has found support for (and
which keep coming up as tentative C++ proposals even without
expected<>/optional<> being in the mix yet!) gets us even further.
There's still ways to screw up error handling (esp. in C++) even with
all that, of course. That doesn't mean that we should give up on
eliminating as many ways of easily screwing up that we can.
>
>> In any case, if we have optional, expected, variant, etc. then we've
>> already got all the problems of nullable types in C#. It would be
>> silly to add all the problems and then fail to add any of the
>> solutions to those problems :)
>
>
> Except that we don't have all the problems, the problem we don't have is that
> we don't have nullable types as a language facility.
I don't follow that argument at all. Being a language facility is
irrelevant to its problems.
Whether you're C# and have a concise but easy-to-misuse language
nullable or you're C++ and have a cumbersome and easy-to-misuse
library optional<>, the underlying problem is whether or not it's easy
to misuse.
You can, again, step out of the C family of languages and find plenty
of examples of Option Types that are both concise and hard to misuse
(and more importantly, easy to use correctly).
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Wed, 3 Jun 2015 21:08:32 +0200
Raw View
> Il giorno 03/giu/2015, alle ore 18:43, Sean Middleditch <sean.middleditch=
@gmail.com> ha scritto:
>=20
> If we keep framing it in what C++ was able to do in 1998, then the option=
s always all come out looking bad.
>=20
+1
> Research has gone on in error-handling mechanisms since C++ first arose. =
There have been more options since before C++ even existed.
>=20
> One could overcome most (all, I think) of the problems of exceptions and =
today's expected by using the following further improvements. The following=
are partially implementable in C++ today with a some templates, a few macr=
os, and a couple big limitations/restrictions, but some of the more interes=
ting bits are not super feasible in C++ today without some language evoluti=
on:
>=20
> - expected<> cannot be unwrapped without checking for errors:
>=20
> .value() or the like would simply not exist. Code would be required to wo=
rk as follows:
>=20
> expected.when {
> case good (auto value) { use value; }
> case failed (auto error) { handle error; }
> }
>=20
> This is what you see in most functional languages.
>=20
Although I love pattern matching as found in functional languages,
I don=E2=80=99t think you can add pattern matching syntax to C++ without
first doing an overhauled of the entire type system to truly support
algebraic data types.
> Note that you can almost emulate this today by using lambdas and a .when(=
good_callback, error_callback) interface:
>=20
> expected.when(
> [](auto& good) { use value; },
> [](auto& error) { handle_error });
>=20
> The problem there is that you can't return from the callbacks usefully, w=
hich poses severe usability issues for many common cases (especially the er=
ror case where your preferred action may be to cease further execution of t=
he enclosing function).
>=20
You can implement when to return the common type of the return types of bot=
h lambdas.
There is still the problem of how to interrupt control flow from inside the=
lambda, though.
> This avoid accidental use-before-check, but does not avoid accidental unu=
sed-and-unchecked (you could just ignore your expected values).
>=20
> - A further extension of this then is the unwrap-if-you-can operator, let=
ting you write convenient shorthand like:
>=20
> result =3D expected?.foo?.bar();
> // translates to
> result =3D bool(expected) ? bool(expected->foo) ? expected->foo->bar() =
: expected->foo.error() : expected.error();
>=20
> The nice thing about this is that can extend to many other useful context=
s. Consider optional:
>=20
> optional<my_type> a =3D ...;
>=20
> auto b =3D my_type?.foo(); // b will be an optional of whatever foo() r=
eturns, and may either be engaged or nullopt.
>=20
> And the same for other types like variant, home-grown error wrappers in e=
xisting libraries and interfaces, iterators/cursors that know if they're va=
lid or not, and so on.
>=20
> Would probably want ?., ?->, and unary ?* to cover all three major cases =
of unwrapping today. (Syntax is just a strawman, of course.)
>=20
With the already mentioned await syntax you already have an alternative to =
those keywords,
although the syntax to chain them is ugly:
optional<T> a =3D =E2=80=A6;
auto b =3D (await (await a).foo()).bar();
> - expected can contain more than one type of error:
>=20
> expected<int, parse_error, io_error>
>=20
> Solves one of the problems you outlined in the first post. this is possib=
le today of course without new syntax or features.
>=20
> The automatic unwrapping code above automatically folds errors into a sin=
gle union of all error types that may occur in the expression.
>=20
> This support also basically turns expected into a variant of variant (sor=
ry) in which one of the cases is explicitly treated as the "good" case and =
the others are all "error" cases. e.g., expected might even just become:
>=20
> template <class V, class... E>
> expected =3D variant<good<V>, fail<E...>>;
>=20
> - expression-try integrated with expected and flow control
>=20
> This allows code to more easily halt execution of the current context. So=
you could write this:
>=20
> expected<int, error> foo(int a) {
> int b =3D a + try some_fallable_function();
>=20
> return other_stuff(b);
> }
>=20
> and it becomes equivalent to:
>=20
> expected<int, error> foo(int a) {
> some_fallable_function().when {
> case good (auto& tmp): {
> int b =3D a + tmp;
> return other_stuff(b); }
> case error (auto& e): return e;
> }
> }
>=20
> That is, it unwraps an expected if it's good, and otherwise immediately r=
eturns the contained error otherwise.
>=20
> I'm led to believe from the last thread that Gor's awaitable functions pr=
oposal might allow the above, albeit with a somewhat surprising keyword (aw=
ait) in place of try.
>=20
Yes, it allows the above. Someone could propose to make the try keyword in =
that position mean the same
as =E2=80=98await=E2=80=99. I don=E2=80=99t see grammar ambiguities because=
currently try is always followed by an =E2=80=98{'
and an expression cannot start with =E2=80=98{=E2=80=98.
> - Existing exception-based code can be made to work with helpers
>=20
> This would include a statement that does the equivalent of today's try/ca=
tch but automatically returns the exception in the latter case. Something l=
ike:
>=20
> expected<int, error> foo() {
> inline try {
> return some_throwing_function();
> }
> }
>=20
> This has the further advantage over today's exceptions that (a) changing =
the signature of foo from one that does not fail to one that does forces yo=
u to update and acknowledge the change in interface at call sites rather th=
an introducing silent bugs or completely unknown code flows; and (b) fixes =
the problems of the failed throws approach by making the list of possible e=
rrors part of the function signature, and in a way that does not automatica=
lly require calling functions to adjust if they just pass the error through=
thanks to auto-return-type-deduction and the above try-expression syntax.
>=20
> Likewise, code that unwraps an expected or throws the contained error (wh=
ich we have today) can work. I dislike this one because it makes it too eas=
y to accidentally throw an exception. I'd at least like this function to be=
named appropriately, e.g. .value_or_throw() to avoid accidental/incidental=
misuse.
>=20
There is not the need for a specific syntax. I can imagine the
implementation of an utility function that do that generically:
expected<int, error> foo() {
std::wrap_exception<error>([] {
return some_throwing_function();
});
}
Note that with the above you can even declare the function as auto foo() {.=
...}
> This would work even better if all C++ functions where noexcept(true) by =
default and noexcept(false) were the opt-in case, allowing the compiler to =
make more intelligent choices for the programmer, but of course that's not =
likely to ever become the case for C++ for back-compat reasons. :(
>=20
R.I.P. sane design.
> Note that the previous item's expression-try should not automatically cat=
ch exceptions, as expression-try has to know the resulting type of its expe=
cted<>, which is not possible with general exception catching in C++ (you c=
an't even just wrap std::exception for noexcept(false) functions without ca=
using a ton of issues). Conversion from C++ exceptions to expected<> must b=
e more explicitly opted-in to by the programmer to avoid type system limita=
tions and performance issues.
>=20
>=20
>=20
> Note that Rust is exploring a similar-ish route with expression-try and u=
nwrapping. They have less need for such a mechanism because they're already=
a functional-paradigm-ready language with first-class sum types, pattern m=
atching, and no existing misdesigned exception mechanism to work around; th=
eir RFCs on expression-try are more about ease-of-use/ergonomics than it is=
for fixing a major failing of the language like it would be for C++. https=
://github.com/rust-lang/rfcs/pull/243 is just one of said RFCs, for your ed=
ification.
>=20
Nice link.
Greetings,
Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 3 Jun 2015 22:13:09 +0300
Raw View
On 3 June 2015 at 22:08, Sean Middleditch <sean@middleditch.us> wrote:
> It is however disingenuous to claim that since it's better than today
> that we shouldn't strive for even better. expected<> today if it lands
I never made such a claim. What I tried to say was that I'd hate to not
have things like expected::value() and be forced to use pattern matching.
Pattern matching is great, but it's no panacea.
>> That's great, but I see no reason why expected shouldn't have a value(). If you
>> don't want to use such a function, don't use it.
> Out in the real world of everyday software developers, people pick the
> paths of least resistance. If there's a .value(), it's going to be
> used far more often than it should (if not on _your_ project, or even
> on mine, certainly on thousands of others), mostly out of ignorance or
> laziness.
I give rather more credit to people's ability to choose the right tool for their
own uses.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 3 Jun 2015 14:01:51 -0700 (PDT)
Raw View
------=_Part_229_1707018042.1433365311135
Content-Type: multipart/alternative;
boundary="----=_Part_230_1618191621.1433365311135"
------=_Part_230_1618191621.1433365311135
Content-Type: text/plain; charset=UTF-8
On Wednesday, June 3, 2015 at 9:48:21 AM UTC-4, Nicola Gigante wrote:
>
> Il giorno 03/giu/2015, alle ore 07:09, Nicol Bolas <jmck...@gmail.com
> <javascript:>> ha scritto:
>
> That all brings me to a number of conclusions:
>
> 1) Exceptions work best in non-local error handling contexts. Local error
> handling best works via `expected`, except where `expected` cannot be used
> or is poor at the job.
>
> 2) The difference between local and non-local handling *cannot be known
> to the library*. It may guess and hope, but there are usually legitimate
> cases where a user might handle errors one way or the other.
>
> 3) Where possible, allow the user to decide whether errors are handled
> locally or not. As such, functions that error should have two versions: one
> that throws and one that uses `expected`.
>
>
> Agreed.
>
You... do? The entire rest of your post seems to disagree.
To me, you post made the following points: You stated that expected is the
right way to handle most errors, defending this with arguments from the
functional programming world. The only errors you conceded ought to be
handled by exeptions were either those cases where `expected` can't work or
I/O, which functional programming handles a different way. You believe so
strongly in `expected` in point of fact that you want to *add special
syntax to the language* just to support the construct more fully
(alterations to `await`, presumably based on some generic interface.
Because that worked out so well for range-based for).
You all but stated that having a parsing system throw exceptions was a
priori the wrong way to deal with them.
And yet, you agree that libraries, including parsing libraries, should
offer both interfaces where possible? Why do you agree with that?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_230_1618191621.1433365311135
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, June 3, 2015 at 9:48:21 AM UTC-4, Nicola Gig=
ante wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-=
wrap:break-word"><div><blockquote type=3D"cite"><div>Il giorno 03/giu/2015,=
alle ore 07:09, Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"IJFaXu05BTUJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;">jmck...@gmail.com</a>> ha scritto:</div><br></blockquote></d=
iv></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div sty=
le=3D"word-wrap:break-word"><div><blockquote type=3D"cite"><div><div dir=3D=
"ltr">That all brings me to a number of conclusions:<br><br>1) Exceptions w=
ork best in non-local error handling contexts. Local error handling best wo=
rks via `expected`, except where `expected` cannot be used or is poor at th=
e job.<br><br>2) The difference between local and non-local handling <i>can=
not be known to the library</i>. It may guess and hope, but there are usual=
ly legitimate cases where a user might handle errors one way or the other.<=
br><br>3) Where possible, allow the user to decide whether errors are handl=
ed locally or not. As such, functions that error should have two versions: =
one that throws and one that uses `expected`.<br></div><div><br></div></div=
></blockquote><div><br></div><div>Agreed.</div></div></div></blockquote><di=
v><br><br>You... do? The entire rest of your post seems to disagree.<br><br=
>To me, you post made the following points: You stated that expected is the=
right way to handle most errors, defending this with arguments from the fu=
nctional programming world. The only errors you conceded ought to be handle=
d by exeptions were either those cases where `expected` can't work or I/O, =
which functional programming handles a different way. You believe so strong=
ly in `expected` in point of fact that you want to <i>add special syntax to=
the language</i> just to support the construct more fully (alterations to =
`await`, presumably based on some generic interface. Because that worked ou=
t so well for range-based for).<br><br>You all but stated that having a par=
sing system throw exceptions was a priori the wrong way to deal with them.<=
br><br>And yet, you agree that libraries, including parsing libraries, shou=
ld offer both interfaces where possible? Why do you agree with that?<br></d=
iv></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_230_1618191621.1433365311135--
------=_Part_229_1707018042.1433365311135--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 3 Jun 2015 15:41:24 -0700 (PDT)
Raw View
------=_Part_1876_1119523120.1433371284605
Content-Type: multipart/alternative;
boundary="----=_Part_1877_1720846473.1433371284606"
------=_Part_1877_1720846473.1433371284606
Content-Type: text/plain; charset=UTF-8
On Wednesday, June 3, 2015 at 12:43:07 PM UTC-4, Sean Middleditch wrote:
>
> If we keep framing it in what C++ was able to do in 1998, then the options
> always all come out looking bad.
>
> Research has gone on in error-handling mechanisms since C++ first arose.
> There have been more options since before C++ even existed.
>
> One could overcome most (all, I think) of the problems of exceptions and
> today's expected by using the following further improvements. The following
> are partially implementable in C++ today with a some templates, a few
> macros, and a couple big limitations/restrictions, but some of the more
> interesting bits are not super feasible in C++ today without some language
> evolution:
>
> - expected<> cannot be unwrapped without checking for errors:
>
- expected can contain more than one type of error:
>
- expression-try integrated with expected and flow control
>
None of these actually solve the problem in question. The fundamental
"problem" of `expected` is that it *forces local handling* of errors. If
you don't *want* to handle the error locally, you are still forced to
explicitly write something in your local code. All these suggestions do is
change what you have to write; you still have to write *something*.
With exceptions, you need write nothing. Uncaught exceptions do not disturb
the intervening code (outside of having to unwind the stack and so forth).
For some people, this is a problem; for others, it's a feature. I believe
that whether it's a feature or a problem depends on the particular use
case, as I've tried to explain here. And therefore, APIs that can fail
should offer the choice, not force one style.
Not all problems are the same. Sometimes, what you think is a local problem
can be treated as a global problem.
> This has the further advantage over today's exceptions that (a) changing
> the signature of foo from one that does not fail to one that does forces
> you to update and acknowledge the change in interface at call sites rather
> than introducing silent bugs or completely unknown code flows;
>
This presupposes that the *local caller of the function* is capable of, or
interested in, handling the failure. Otherwise, you have to write a lot of
syntax that is nothing more than "go find the guy who called me that can
deal with this."
> (b) fixes the problems of the failed throws approach by making the list of
> possible errors part of the function signature,
>
Yeah, Java tried that with `throw` specifications. It is fairly widely
agreed that this approach *sucked*.
Also, it is impossible to pass around arbitrary callables where they can
each throw their own unique types of errors. Imagine an event system, where
the person who called the event can handle a certain set of exceptions. Why
does the *event system itself* need to know or care what that set of
exceptions is? All it needs to do is store functors and call them.
> and in a way that does not automatically require calling functions to
> adjust if they just pass the error through thanks to
> auto-return-type-deduction and the above try-expression syntax.
>
Not everyone can use auto-return-type-deduction or calling into some other
context to resolve problems. Not everyone sticks all their code into
headers, you know.
Oh, and you seem to have arrived at a contradiction. What good is "making
the list of possible errors part of the function signature" if
auto-return-type-deduction means that nobody can actually see the "list of
possible errors"? Oh yes, the compiler knows what they are, but user's
don't. If the goal was self-documenting code, auto-return-type-deduction is
exactly what you *don't* want.
And since there's no syntax that will cause a failure of some kind if you
don't check for a particular type of error, it is very easy to miss a
specific case without anyone realizing. So this is not better than
exceptions in any way. Indeed, it's worse; at least with exceptions, you
either catch it or halt. This way, you catch it or... the program just
keeps going.
I'm not saying that the things you want are necessarily bad. Well, not all
of them. Well, not some of them. What I'm saying is that they do not
replace exceptions, nor do they justify APIs that use `expected` as the
exclusive way to communicate errors.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1877_1720846473.1433371284606
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, June 3, 2015 at 12:43:07 PM UTC-4, Sean Midd=
leditch wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
>If we keep framing it in what C++ was able to do in 1998, then the options=
always all come out looking bad.<div><br></div><div>Research has gone on i=
n error-handling mechanisms since C++ first arose. There have been more opt=
ions since before C++ even existed.</div><div><br></div><div>One could over=
come most (all, I think) of the problems of exceptions and today's expected=
by using the following further improvements. The following are partially i=
mplementable in C++ today with a some templates, a few macros, and a couple=
big limitations/restrictions, but some of the more interesting bits are no=
t super feasible in C++ today without some language evolution:</div></div><=
/blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><br></div><div>- expected<> cannot be unwrapped without checking =
for errors:</div></div></blockquote><div><blockquote style=3D"margin: 0px 0=
px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;=
" class=3D"gmail_quote"><div>- expected can contain more than one type of e=
rror:</div></blockquote><blockquote style=3D"margin: 0px 0px 0px 0.8ex; bor=
der-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class=3D"gmail_=
quote"><div>- expression-try integrated with expected and flow control <br>=
</div></blockquote><br><br>None of these actually solve the problem in ques=
tion. The fundamental "problem" of `expected` is that it <i>forces local ha=
ndling</i> of errors. If you don't <i>want</i> to handle the error locally,=
you are still forced to explicitly write something in your local code. All=
these suggestions do is change what you have to write; you still have to w=
rite <i>something</i>.<br><br>With exceptions, you need write nothing. Unca=
ught exceptions do not disturb the intervening code (outside of having to u=
nwind the stack and so forth).<br><br>For some people, this is a problem; f=
or others, it's a feature. I believe that whether it's a feature or
a problem depends on the particular use case, as I've tried to explain=20
here. And therefore, APIs that can fail should offer the choice, not=20
force one style.<br><br>Not all problems are the same. Sometimes, what you =
think is a local problem can be treated as a global problem.<br> </div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><=
div>This has the further advantage over today's exceptions that (a) changin=
g the signature of foo from one that does not fail to one that does forces =
you to update and acknowledge the change in interface at call sites rather =
than introducing silent bugs or completely unknown code flows;</div></div><=
/blockquote><div><br>This presupposes that the <i>local caller of the funct=
ion</i> is capable of, or interested in, handling the failure. Otherwise, y=
ou have to write a lot of syntax that is nothing more than "go find the guy=
who called me that can deal with this."<br> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div> (b) fixes the problems o=
f the failed throws approach by making the list of possible errors part of =
the function signature,</div></div></blockquote><div><br>Yeah, Java tried t=
hat with `throw` specifications. It is fairly widely agreed that this appro=
ach <i>sucked</i>.<br><br>Also, it is impossible to pass around arbitrary c=
allables where they can each throw their own unique types of errors. Imagin=
e an event system, where the person who called the event can handle a certa=
in set of exceptions. Why does the <i>event system itself</i> need to know =
or care what that set of exceptions is? All it needs to do is store functor=
s and call them.<br> </div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div dir=3D"ltr"><div> and in a way that does not automatically require c=
alling functions to adjust if they just pass the error through thanks to au=
to-return-type-deduction and the above try-expression syntax.</div></div></=
blockquote><div><br>Not everyone can use auto-return-type-deduction or call=
ing into some other context to resolve problems. Not everyone sticks all th=
eir code into headers, you know.<br><br>Oh, and you seem to have arrived at=
a contradiction. What good is "making the list of possible errors part of =
the function signature" if auto-return-type-deduction means that nobody can=
actually see the "list of possible errors"? Oh yes, the compiler knows wha=
t they are, but user's don't. If the goal was self-documenting code, auto-r=
eturn-type-deduction is exactly what you <i>don't</i> want.<br><br>And sinc=
e there's no syntax that will cause a failure of some kind if you don't che=
ck for a particular type of error, it is very easy to miss a specific case =
without anyone realizing. So this is not better than exceptions in any way.=
Indeed, it's worse; at least with exceptions, you either catch it or halt.=
This way, you catch it or... the program just keeps going.<br><br>I'm not =
saying that the things you want are necessarily bad. Well, not all of them.=
Well, not some of them. What I'm saying is that they do not replace except=
ions, nor do they justify APIs that use `expected` as the exclusive way to =
communicate errors.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1877_1720846473.1433371284606--
------=_Part_1876_1119523120.1433371284605--
.
Author: Jeremy Maitin-Shepard <jeremy@jeremyms.com>
Date: Wed, 3 Jun 2015 17:09:22 -0700 (PDT)
Raw View
------=_Part_5908_766582696.1433376562168
Content-Type: multipart/alternative;
boundary="----=_Part_5909_1200973319.1433376562168"
------=_Part_5909_1200973319.1433376562168
Content-Type: text/plain; charset=UTF-8
On Wednesday, June 3, 2015 at 3:41:24 PM UTC-7, Nicol Bolas wrote:
>
>
> With exceptions, you need write nothing. Uncaught exceptions do not
> disturb the intervening code (outside of having to unwind the stack and so
> forth).
>
> For some people, this is a problem; for others, it's a feature. I believe
> that whether it's a feature or a problem depends on the particular use
> case, as I've tried to explain here. And therefore, APIs that can fail
> should offer the choice, not force one style.
>
I agree with this view. Depending on whether you want to handle the error
locally or non-locally, different APIs may be more convenient. However,
the conclusion that any API that can fail should provide two different ways
of reporting it, seems very unfortunate. With this scheme, the interface
to a library becomes twice as large. It also may be a lot more work to
implement and test, because you often want to provide richer information
via an exception than you can with an error code, which precludes making
the throwing version a trivial wrapper around the error code version (even
though you still have access to the arguments to the outer-most library
call, any richer error information from a lower-level function that was
called has already been lost if you call the error code version of it). It
is easier to make the error code version a trivial wrapper around the
exception-throwing version, but then you have to have exceptions enabled
and possibly pay the exception handling cost just to use error codes, and
writing all of these wrappers is still annoying.
Maybe we will have to declare defeat and go with this in some cases, but I
really hope we can come up with something that is flexible but avoids this
duplication.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_5909_1200973319.1433376562168
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, June 3, 2015 at 3:41:24 PM UTC-7, Ni=
col Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r"><br><div>With exceptions, you need write nothing. Uncaught exceptions do=
not disturb the intervening code (outside of having to unwind the stack an=
d so forth).<br><br>For some people, this is a problem; for others, it's a =
feature. I believe that whether it's a feature or
a problem depends on the particular use case, as I've tried to explain=20
here. And therefore, APIs that can fail should offer the choice, not=20
force one style.<br></div></div></blockquote><div><br>I agree with this vie=
w. Depending on whether you want to handle the error locally or non-l=
ocally, different APIs may be more convenient. However, the conclusio=
n that any API that can fail should provide two different ways of reporting=
it, seems very unfortunate. With this scheme, the interface to a lib=
rary becomes twice as large. It also may be a lot more work to implem=
ent and test, because you often want to provide richer information via an e=
xception than you can with an error code, which precludes making the throwi=
ng version a trivial wrapper around the error code version (even though you=
still have access to the arguments to the outer-most library call, any ric=
her error information from a lower-level function that was called has alrea=
dy been lost if you call the error code version of it). It is easier =
to make the error code version a trivial wrapper around the exception-throw=
ing version, but then you have to have exceptions enabled and possibly pay =
the exception handling cost just to use error codes, and writing all of the=
se wrappers is still annoying.<br><br>Maybe we will have to declare defeat =
and go with this in some cases, but I really hope we can come up with somet=
hing that is flexible but avoids this duplication.</div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5909_1200973319.1433376562168--
------=_Part_5908_766582696.1433376562168--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 3 Jun 2015 17:46:16 -0700 (PDT)
Raw View
------=_Part_2069_915796220.1433378777052
Content-Type: multipart/alternative;
boundary="----=_Part_2070_771771491.1433378777052"
------=_Part_2070_771771491.1433378777052
Content-Type: text/plain; charset=UTF-8
On Wednesday, June 3, 2015 at 8:09:22 PM UTC-4, Jeremy Maitin-Shepard wrote:
>
> On Wednesday, June 3, 2015 at 3:41:24 PM UTC-7, Nicol Bolas wrote:
>>
>>
>> With exceptions, you need write nothing. Uncaught exceptions do not
>> disturb the intervening code (outside of having to unwind the stack and so
>> forth).
>>
>> For some people, this is a problem; for others, it's a feature. I believe
>> that whether it's a feature or a problem depends on the particular use
>> case, as I've tried to explain here. And therefore, APIs that can fail
>> should offer the choice, not force one style.
>>
>
> I agree with this view. Depending on whether you want to handle the error
> locally or non-locally, different APIs may be more convenient. However,
> the conclusion that any API that can fail should provide two different ways
> of reporting it, seems very unfortunate. With this scheme, the interface
> to a library becomes twice as large. It also may be a lot more work to
> implement and test, because you often want to provide richer information
> via an exception than you can with an error code, which precludes making
> the throwing version a trivial wrapper around the error code version (even
> though you still have access to the arguments to the outer-most library
> call, any richer error information from a lower-level function that was
> called has already been lost if you call the error code version of it). It
> is easier to make the error code version a trivial wrapper around the
> exception-throwing version, but then you have to have exceptions enabled
> and possibly pay the exception handling cost just to use error codes, and
> writing all of these wrappers is still annoying.
>
> Maybe we will have to declare defeat and go with this in some cases, but I
> really hope we can come up with something that is flexible but avoids this
> duplication.
>
I agree that it is unfortunate, but I also don't see any way around it. Not
without doing something that will be inconvenient to a non-trivial number
of people.
You don't want to start throwing smart pointers to large objects as
`expected` errors, since that requires dynamic memory allocation; that'd be
bad for people who want to have cheap error detection (or those who want to
have tight control over dynamic memory allocation). And as you point out,
if it tries to convert the `expected` into an exception, you can lose
valuable semantic information.
I think the best we can do is let library implementers do whatever they can
to mitigate the issue. Implementers will have to have a third internal
function, called by the other two, that does the meat of the work, but also
returns whatever semantic information might need to be thrown in an
exception case.
It's not a great solution, as it requires a lot of route work, but it is
one that will work on platforms that don't allow exceptions. And it allows
users to decide what kind of error handling they need on a case-by-case
basis.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2070_771771491.1433378777052
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, June 3, 2015 at 8:09:22 PM UTC-4, Jeremy Mai=
tin-Shepard wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr">On Wednesday, June 3, 2015 at 3:41:24 PM UTC-7, Nicol Bolas wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><div>With exceptio=
ns, you need write nothing. Uncaught exceptions do not disturb the interven=
ing code (outside of having to unwind the stack and so forth).<br><br>For s=
ome people, this is a problem; for others, it's a feature. I believe that w=
hether it's a feature or
a problem depends on the particular use case, as I've tried to explain=20
here. And therefore, APIs that can fail should offer the choice, not=20
force one style.<br></div></div></blockquote><div><br>I agree with this vie=
w. Depending on whether you want to handle the error locally or non-l=
ocally, different APIs may be more convenient. However, the conclusio=
n that any API that can fail should provide two different ways of reporting=
it, seems very unfortunate. With this scheme, the interface to a lib=
rary becomes twice as large. It also may be a lot more work to implem=
ent and test, because you often want to provide richer information via an e=
xception than you can with an error code, which precludes making the throwi=
ng version a trivial wrapper around the error code version (even though you=
still have access to the arguments to the outer-most library call, any ric=
her error information from a lower-level function that was called has alrea=
dy been lost if you call the error code version of it). It is easier =
to make the error code version a trivial wrapper around the exception-throw=
ing version, but then you have to have exceptions enabled and possibly pay =
the exception handling cost just to use error codes, and writing all of the=
se wrappers is still annoying.<br><br>Maybe we will have to declare defeat =
and go with this in some cases, but I really hope we can come up with somet=
hing that is flexible but avoids this duplication.<br></div></div></blockqu=
ote><div> <br>I agree that it is unfortunate, but I also don't see any=
way around it. Not without doing something that will be inconvenient to a =
non-trivial number of people.<br><br>You don't want to start throwing smart=
pointers to large objects as `expected` errors, since that requires dynami=
c memory allocation; that'd be bad for people who want to have cheap error =
detection (or those who want to have tight control over dynamic memory allo=
cation). And as you point out, if it tries to convert the `expected` into a=
n exception, you can lose valuable semantic information.<br><br>I think the=
best we can do is let library implementers do whatever they can to mitigat=
e the issue. Implementers will have to have a third internal function, call=
ed by the other two, that does the meat of the work, but also returns whate=
ver semantic information might need to be thrown in an exception case.<br><=
br>It's not a great solution, as it requires a lot of route work, but it is=
one that will work on platforms that don't allow exceptions. And it allows=
users to decide what kind of error handling they need on a case-by-case ba=
sis.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2070_771771491.1433378777052--
------=_Part_2069_915796220.1433378777052--
.
Author: Sean Middleditch <sean@middleditch.us>
Date: Wed, 3 Jun 2015 22:16:15 -0700
Raw View
On Wed, Jun 3, 2015 at 3:41 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Wednesday, June 3, 2015 at 12:43:07 PM UTC-4, Sean Middleditch wrote:
>> - expected<> cannot be unwrapped without checking for errors:
>>
>> - expected can contain more than one type of error:
>>
>> - expression-try integrated with expected and flow control
>
>
>
> None of these actually solve the problem in question. The fundamental
> "problem" of `expected` is that it forces local handling of errors. If you
> don't want to handle the error locally, you are still forced to explicitly
> write something in your local code. All these suggestions do is change what
> you have to write; you still have to write something.
>
> With exceptions, you need write nothing.
Which is a big misconception of exceptions proponents. Given a few
decades of paying close attention to the bugs that have arisen because
people didn't pay attention to when and where exceptions can and will
be thrown (or because later refactorings introduced new ones that old
dependent code wasn't prepared for)...
In any case, though, I'm not interested in arguing this point ad
nauseum. If we disagree, we disagree, and that's cool; exceptions
aren't going anywhere. I'm not arguing otherwise. They _can't_ go
anywhere in C++, after all. Now, if we were debating the formation of
a C+=2 maybe... ;)
>
>>
>> This has the further advantage over today's exceptions that (a) changing
>> the signature of foo from one that does not fail to one that does forces you
>> to update and acknowledge the change in interface at call sites rather than
>> introducing silent bugs or completely unknown code flows;
>
>
> This presupposes that the local caller of the function is capable of, or
> interested in, handling the failure. Otherwise, you have to write a lot of
> syntax that is nothing more than "go find the guy who called me that can
> deal with this."
It is not. It only presupposed that the local caller must acknowledge
(self-document, even) what they already must do - be prepared for
letting a failure happen at that point without leaking memory,
corrupting a data structure, or otherwise misbehaving. Stating clearly
and definitely: "you can halt my execution here and force me to exit,
if you really want to; I don't mind."
Explicitness is a good thing. Whitelisting instead of blacklisting is
a better approach to constraining the surface area of unintended
failures.
Failing to handle an exceptions is a coding error that manifests as a
run-time failure. The stuff I was talking about makes that broken code
turn into a compile-time error. That's been a rather key element of
C/C++98/C++11/C++14/etc. over the competitors: catch programmer
mistakes early and before they manifest as ten-thousand-dollar bugs in
production. :)
There's not much worse than an error-handling mechanism that creates errors. :p
But, again, I'm talking about improvements to expected, not using it
replace exceptions everywhere, which is obviously impossible and
utterly pointless to argue about.
Exceptions will always be there. A "new" (to the C++ neighborhood)
mechanism can exist that offers more strictness without sacrificing
your ability to throw as many exceptions as you want. Make an
exception pinata that throws delicious exception candy all over the
place when it breaks. These mechanisms can live in peace and harmony
with each other, despite their cultural differences. :)
>
>>
>> (b) fixes the problems of the failed throws approach by making the list of
>> possible errors part of the function signature,
>
>
> Yeah, Java tried that with `throw` specifications. It is fairly widely
> agreed that this approach sucked.
I think there's subtler issues there than most people realize. It's
very easy to confuse implementation of an idea with the idea itself.
>
> Also, it is impossible to pass around arbitrary callables where they can
> each throw their own unique types of errors. Imagine an event system, where
> the person who called the event can handle a certain set of exceptions. Why
> does the event system itself need to know or care what that set of
> exceptions is? All it needs to do is store functors and call them.
Not that the problem hasn't been solved in FP contexts for some time
now. One could return an expected<T, Err> with Err being a
type-deleted exception wrapper, and the error can be rethrown once the
event system receives the result. Which you actually _have_ to do if
you're working with an asynchronous event system, so it's not even a
new concept to C++. Nor to JavaScript nor to Scala nor... you get the
point. :)
That said, an "arbitrary callable" that has an unconstrained interface
(it can throw anything it wants) sounds like a design failure to me.
Certainly you're documenting and constraining _which_ exceptions an
"arbitrary" callee can throw so you know which exceptions to actually
catch, yes? I'd almost definitely make any event library explicitly
only work with noexcept(true) functions and pray that N4533 gets
accepted.
I'm gonna go out on a limb here and presuppose that most code that
reads mouse input and forwards it on to a GUI library isn't exactly
prepared for the GUI library to send back a bad_cast from a
lexical_cast function that the mouse code never even uses... but users
just love it when their app with an hour's worth of work suddenly
terminates because someone was super keen on needing slightly fewer
keystrokes while coding. :p
>
>>
>> and in a way that does not automatically require calling functions to
>> adjust if they just pass the error through thanks to
>> auto-return-type-deduction and the above try-expression syntax.
>
>
> Not everyone can use auto-return-type-deduction or calling into some other
> context to resolve problems. Not everyone sticks all their code into
> headers, you know.
.... Said to the guy who's literally in the tail end of weeks-long
process of ripping out every single last near-pointless use of Boost
from a ~2 million line game engine and tool suite "just" to gain a ~5%
build time improvement and ~15% debug binary size reduction. :p
That said, no, of course we don't all put code in headers. That's not
super relevant to the discussion, is it?
>
> Oh, and you seem to have arrived at a contradiction. What good is "making
> the list of possible errors part of the function signature" if
> auto-return-type-deduction means that nobody can actually see the "list of
> possible errors"? Oh yes, the compiler knows what they are, but user's
> don't. If the goal was self-documenting code, auto-return-type-deduction is
> exactly what you don't want.
You're over-extrapolating from an example that I whipped together in
30 seconds in Gmail.
If you don't like auto-return-type, don't use it. Nothing I mentioned
mandates them. I made a point that there's an ergonomics gain there
for people who do use them.
>
> And since there's no syntax that will cause a failure of some kind if you
> don't check for a particular type of error, it is very easy to miss a
> specific case without anyone realizing. So this is not better than
> exceptions in any way. Indeed, it's worse; at least with exceptions, you
> either catch it or halt. This way, you catch it or... the program just keeps
> going.
Most languages with pattern matching actually require you to handle
all cases, or explicitly add in the default case (akin to catching an
exception and ignoring it). Most C++ compilers already do this today
in switch-statements with a warning. One would expect a quality
extension to C++ for pattern matching to follow suit.
The one case not handled well by expected-like error handling is
fallable functions that don't return an interesting value in the first
place. Because there's no return value you're trying to unwrap,
there's nothing to force you to acknowledge any errors at compile
time. I'd still rather cover many cases than none of them at all,
though I would like to cover all of them... I haven't found an
entirely good solution here nor am I yet aware of any research into
the problem in other languages. I think it might need a
"do_not_ignore_result" sort of function facility, but I'm not yet
convinced.
--
Sean Middleditch
http://seanmiddleditch.com
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 4 Jun 2015 00:00:51 -0700 (PDT)
Raw View
------=_Part_42_2083467458.1433401251667
Content-Type: multipart/alternative;
boundary="----=_Part_43_2116702271.1433401251667"
------=_Part_43_2116702271.1433401251667
Content-Type: text/plain; charset=UTF-8
On Thursday, June 4, 2015 at 1:16:18 AM UTC-4, Sean Middleditch wrote:
>
> On Wed, Jun 3, 2015 at 3:41 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
> > On Wednesday, June 3, 2015 at 12:43:07 PM UTC-4, Sean Middleditch wrote:
> >> - expected<> cannot be unwrapped without checking for errors:
> >>
> >> - expected can contain more than one type of error:
> >>
> >> - expression-try integrated with expected and flow control
> >
> >
> >
> > None of these actually solve the problem in question. The fundamental
> > "problem" of `expected` is that it forces local handling of errors. If
> you
> > don't want to handle the error locally, you are still forced to
> explicitly
> > write something in your local code. All these suggestions do is change
> what
> > you have to write; you still have to write something.
> >
> > With exceptions, you need write nothing.
>
> Which is a big misconception of exceptions proponents. Given a few
> decades of paying close attention to the bugs that have arisen because
> people didn't pay attention to when and where exceptions can and will
> be thrown (or because later refactorings introduced new ones that old
> dependent code wasn't prepared for)...
>
> In any case, though, I'm not interested in arguing this point ad
> nauseum. If we disagree, we disagree, and that's cool; exceptions
> aren't going anywhere. I'm not arguing otherwise. They _can't_ go
> anywhere in C++, after all. Now, if we were debating the formation of
> a C+=2 maybe... ;)
>
There are several problems with that. The main one is this: you're arguing
that `expected` is *superior* to exceptions. That enforced local error
handling is fundamentally better than a mechanism that doesn't disturb
local code that does not need to be involved in error processing. That
disturbing code that doesn't necessarily need to be disturbed leads to less
buggy code.
That's an important problem because, well, if you believe that X is
fundamentally superior to Y, then your natural inclination will be to do
everything you can to promote X in favor of Y. Such thinking leads to
hijacking other features (like `await`, which has nothing to do with
`expected`) to help promote X, making it take less syntax to use. Such
thinking leads to adding new syntax (a precious resource already) to make X
take less syntax to use. Such thinking will lead to saying, "parsing errors
should only be provided via `expected`". And so forth.
See, everyone says that exceptions "aren't going anywhere". But the fact
is, they most assuredly *can*. They can "go anywhere" through simple
neglect. If everyone jumps on the "use `expected` everywhere" bandwagon,
then exceptions will go away. New library features won't use them, both in
the standard and elsewhere. New containers, ranges, algorithms, etc, all
using `expected` or similar constructs.
And suddenly, our choices of error handling methodology are being made for
us.
That's why we need to focus on both, not try to denigrate one in favor of
the other. Play to each others' strengths and let users decide how to
handle their errors.
>>
> >> This has the further advantage over today's exceptions that (a)
> changing
> >> the signature of foo from one that does not fail to one that does
> forces you
> >> to update and acknowledge the change in interface at call sites rather
> than
> >> introducing silent bugs or completely unknown code flows;
> >
> >
> > This presupposes that the local caller of the function is capable of, or
> > interested in, handling the failure. Otherwise, you have to write a lot
> of
> > syntax that is nothing more than "go find the guy who called me that can
> > deal with this."
>
> It is not. It only presupposed that the local caller must acknowledge
> (self-document, even) what they already must do - be prepared for
> letting a failure happen at that point without leaking memory,
> corrupting a data structure, or otherwise misbehaving. Stating clearly
> and definitely: "you can halt my execution here and force me to exit,
> if you really want to; I don't mind."
>
> Explicitness is a good thing.
No, it is not; sometimes extra syntax is just extra syntax. That's the
whole point of lambdas. That's the whole point of range-based for. That's
the whole point of concepts-lite's new "terse template" syntax. And that's
the whole point of the `await-as-expected-processor` stuff you want.
That's not to say that being explicit is always bad. But to declare that it
is a priori good is simply favoring one coding style over another. And that
*is* bad.
Failing to handle an exceptions is a coding error that manifests as a
> run-time failure. The stuff I was talking about makes that broken code
> turn into a compile-time error.
Except that you haven't *proven* that it is "broken code" yet. If I'm
following exception-safe practices, then I have nothing to worry about with
an exception unwinding the stack through my code. Not to mention that most
"exception-safe practices" are just good C++ practices in general; they'll
defend against errant `return` or `yield` statements too.
Your way gets tons of false positives; it requires that you *constantly*
defend yourself, even when you're in perfectly safe code. Oh yes, you're
sure your code can't fail. But that's only because you've littered your
code everywhere with various minutiae of local error handling, even when
the local code is just passing the error along.
Also, since you're passing it along via `return` or `yield`... you'll still
need most of those exception-safe practices. And if you get them wrong,
then your code is *just as broken* as the exception case.
>
> >>
> >> (b) fixes the problems of the failed throws approach by making the list
> of
> >> possible errors part of the function signature,
> >
> >
> > Yeah, Java tried that with `throw` specifications. It is fairly widely
> > agreed that this approach sucked.
>
> I think there's subtler issues there than most people realize. It's
> very easy to confuse implementation of an idea with the idea itself.
>
Yes, it is possible to confuse them. So... where's that confusion?
Java exception specifications are effectively part of a function's type.
The compiler will detect every attempt to call a function, and it can
detect if any exceptions thrown by that function leak out of the calling
function. In that case, the calling function must explicitly declare that
it emits those exceptions, or a compiler error results. This is propagated
up the entire call-stack, until someone actually handles it.
All of this is just as true of propagating `expected` errors. If the error
cannot be handled locally, you must keep returning the `expected` (thus
making it part of the function's return type) until you finally find
someone who handles it. And, with your "pattern matching" syntax, a
compiler error will result if you don't handle all of the cases.
I fail to see the confusion. Oh, there are differences. But they're still
very comparable in user burden. Only `expected` is even more burdensome.
That said, an "arbitrary callable" that has an unconstrained interface
> (it can throw anything it wants) sounds like a design failure to me.
> Certainly you're documenting and constraining _which_ exceptions an
> "arbitrary" callee can throw so you know which exceptions to actually
> catch, yes? I'd almost definitely make any event library explicitly
> only work with noexcept(true) functions and pray that N4533 gets
> accepted.
>
.... That is patently absurd. Why does a generic event system need to know
or care about what specific errors pass between the code emitting the error
and the code consuming it? It's not handling those errors; it *can't*
handle those errors. Those errors represent a failure of the called process
to complete. The event system is process-agnostic (generally speaking), so
it lacks sufficient knowledge or ability to actually do anything other than
pass the error along.
So why spend the syntax to do so?
Forget an "event" system; just consider std::transform. You pass it a
functor, and it's going to call that functor, storing each value in the
output iterator.
If that process can error... how do you handle that with `expected`? Do you
specialize `std::transform` based on the return type of the functor's
operator(), with a special implementation if it returns an `expected`? Or
does it just store the `expected` object in the output, thus forcing your
output iterator to be able to accept that and error test accordingly?
With an exception, this is trivial; your functor throws. This halts the
process and returns various information. Sadly, you can't get exactly where
you are in the list, but you at least left `transform` and returned to
reasonable code.
What if incrementing the iterator causes an error? Does `std::transform`
have to be written to have ++ return an `expected`? With exceptions, it is
understood how you handle this; with `expected`, it simply doesn't work.
`expected` works in the case of static, human-written function calls; in
the case of dynamic ones, whether runtime polymorphism or compiletime, it
has problems.
>>
> >> and in a way that does not automatically require calling functions to
> >> adjust if they just pass the error through thanks to
> >> auto-return-type-deduction and the above try-expression syntax.
> >
> >
> > Not everyone can use auto-return-type-deduction or calling into some
> other
> > context to resolve problems. Not everyone sticks all their code into
> > headers, you know.
>
> ... Said to the guy who's literally in the tail end of weeks-long
> process of ripping out every single last near-pointless use of Boost
> from a ~2 million line game engine and tool suite "just" to gain a ~5%
> build time improvement and ~15% debug binary size reduction. :p
>
> That said, no, of course we don't all put code in headers. That's not
> super relevant to the discussion, is it?
>
Ahem: "...in a way that does not automatically require calling functions to
adjust if they just pass the error through thanks to
*auto-return-type-deduction*..."
You can't have auto-return-type-deduction if the function body isn't
locally available to the translation unit. So for most code, that means "in
headers". And without auto-return-type-deduction, you can't have "a way
that does not automatically require calling functions to adjust if they
just pass the error through." Those functions will have to explicitly name
the errors being passed through in their return types.
Modules may make it so that we'll all be using auto-return-type-deduction.
But until then...
> And since there's no syntax that will cause a failure of some kind if you
> > don't check for a particular type of error, it is very easy to miss a
> > specific case without anyone realizing. So this is not better than
> > exceptions in any way. Indeed, it's worse; at least with exceptions, you
> > either catch it or halt. This way, you catch it or... the program just
> keeps
> > going.
>
> Most languages with pattern matching actually require you to handle
> all cases, or explicitly add in the default case (akin to catching an
> exception and ignoring it). Most C++ compilers already do this today
> in switch-statements with a warning. One would expect a quality
> extension to C++ for pattern matching to follow suit.
>
Yes. And this "pattern matching" will be *optional*, not mandatory.
Certainly, there has been no proposal about it; the current `expected`
proposal certainly isn't suggesting anything but a library change. So
`expected` cannot be written to assume that it exists.
And quite frankly, I don't think a lot of people will appreciate having to
basically write try/catch blocks to handle `expected`. To my mind, and that
of many others I imagine, `expected` exists to *avoid* that. Which is
basically my point: you keep trying to use `expected` to handle situations
that it's just not intended to handle. It's really good at *local* error
handling. Adding a bunch of features to help it in non-local scenarios is
simply using the wrong tool for the job.
Exceptions are a sledgehammer; expected is a scalpel. Both are good tools
in their domain, yet you seem to be promoting the idea that everyone should
become a surgeon.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_43_2116702271.1433401251667
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, June 4, 2015 at 1:16:18 AM UTC-4, Sean Middle=
ditch wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Wed, Jun 3, 201=
5 at 3:41 PM, Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" gdf=
-obfuscated-mailto=3D"bdRSEZTO2mMJ" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D'javascript:';return true;" onclick=3D"this.href=3D'javascript:';retur=
n true;">jmck...@gmail.com</a>> wrote:
<br>> On Wednesday, June 3, 2015 at 12:43:07 PM UTC-4, Sean Middleditch =
wrote:
<br>>> - expected<> cannot be unwrapped without checking for er=
rors:
<br>>>
<br>>> - expected can contain more than one type of error:
<br>>>
<br>>> - expression-try integrated with expected and flow control
<br>>
<br>>
<br>>
<br>> None of these actually solve the problem in question. The fundamen=
tal
<br>> "problem" of `expected` is that it forces local handling of errors=
.. If you
<br>> don't want to handle the error locally, you are still forced to ex=
plicitly
<br>> write something in your local code. All these suggestions do is ch=
ange what
<br>> you have to write; you still have to write something.
<br>>
<br>> With exceptions, you need write nothing.
<br>
<br>Which is a big misconception of exceptions proponents. Given a few
<br>decades of paying close attention to the bugs that have arisen because
<br>people didn't pay attention to when and where exceptions can and will
<br>be thrown (or because later refactorings introduced new ones that old
<br>dependent code wasn't prepared for)...
<br>
<br>In any case, though, I'm not interested in arguing this point ad
<br>nauseum. If we disagree, we disagree, and that's cool; exceptions
<br>aren't going anywhere. I'm not arguing otherwise. They _can't_ go
<br>anywhere in C++, after all. Now, if we were debating the formation of
<br>a C+=3D2 maybe... ;)<br></blockquote><div><br>There are several problem=
s with that. The main one is this: you're arguing that `expected` is <i>sup=
erior</i> to exceptions. That enforced local error handling is fundamentall=
y better than a mechanism that doesn't disturb local code that does not nee=
d to be involved in error processing. That disturbing code that doesn't nec=
essarily need to be disturbed leads to less buggy code.<br><br>That's an im=
portant problem because, well, if you believe that X is fundamentally super=
ior to Y, then your natural inclination will be to do everything you can to=
promote X in favor of Y. Such thinking leads to hijacking other features (=
like `await`, which has nothing to do with `expected`) to help promote X, m=
aking it take less syntax to use. Such thinking leads to adding new syntax =
(a precious resource already) to make X take less syntax to use. Such think=
ing will lead to saying, "parsing errors should only be provided via `expec=
ted`". And so forth.<br><br>See, everyone says that exceptions "aren't goin=
g anywhere". But the fact is, they most assuredly <i>can</i>. They can "go =
anywhere" through simple neglect. If everyone jumps on the "use `expected` =
everywhere" bandwagon, then exceptions will go away. New library features w=
on't use them, both in the standard and elsewhere. New containers, ranges, =
algorithms, etc, all using `expected` or similar constructs.<br><br>And sud=
denly, our choices of error handling methodology are being made for us.<br>=
<br>That's why we need to focus on both, not try to denigrate one in favor =
of the other. Play to each others' strengths and let users decide how to ha=
ndle their errors.<br><br></div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
">>>
<br>>> This has the further advantage over today's exceptions that (a=
) changing
<br>>> the signature of foo from one that does not fail to one that d=
oes forces you
<br>>> to update and acknowledge the change in interface at call site=
s rather than
<br>>> introducing silent bugs or completely unknown code flows;
<br>>
<br>>
<br>> This presupposes that the local caller of the function is capable =
of, or
<br>> interested in, handling the failure. Otherwise, you have to write =
a lot of
<br>> syntax that is nothing more than "go find the guy who called me th=
at can
<br>> deal with this."
<br>
<br>It is not. It only presupposed that the local caller must acknowledge
<br>(self-document, even) what they already must do - be prepared for
<br>letting a failure happen at that point without leaking memory,
<br>corrupting a data structure, or otherwise misbehaving. Stating clearly
<br>and definitely: "you can halt my execution here and force me to exit,
<br>if you really want to; I don't mind."
<br>
<br>Explicitness is a good thing.</blockquote><div><br>No, it is not; somet=
imes extra syntax is just extra syntax. That's the whole point of lambdas. =
That's the whole point of range-based for. That's the whole point of concep=
ts-lite's new "terse template" syntax. And that's the whole point of the `a=
wait-as-expected-processor` stuff you want.<br><br>That's not to say that b=
eing explicit is always bad. But to declare that it is a priori good is sim=
ply favoring one coding style over another. And that <i>is</i> bad.<br><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;">Failing to handle an exc=
eptions is a coding error that manifests as a
<br>run-time failure. The stuff I was talking about makes that broken code
<br>turn into a compile-time error.</blockquote><div><br>Except that you ha=
ven't <i>proven</i> that it is "broken code" yet. If I'm following exceptio=
n-safe practices, then I have nothing to worry about with an exception unwi=
nding the stack through my code. Not to mention that most "exception-safe p=
ractices" are just good C++ practices in general; they'll defend against er=
rant `return` or `yield` statements too.<br><br>Your way gets tons of false=
positives; it requires that you <i>constantly</i> defend yourself, even wh=
en you're in perfectly safe code. Oh yes, you're sure your code can't fail.=
But that's only because you've littered your code everywhere with various =
minutiae of local error handling, even when the local code is just passing =
the error along.<br><br>Also, since you're passing it along via `return` or=
`yield`... you'll still need most of those exception-safe practices. And i=
f you get them wrong, then your code is <i>just as broken</i> as the except=
ion case.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
>
<br>>>
<br>>> (b) fixes the problems of the failed throws approach by making=
the list of
<br>>> possible errors part of the function signature,
<br>>
<br>>
<br>> Yeah, Java tried that with `throw` specifications. It is fairly wi=
dely
<br>> agreed that this approach sucked.
<br>
<br>I think there's subtler issues there than most people realize. It's
<br>very easy to confuse implementation of an idea with the idea itself.<br=
></blockquote><div><br>Yes, it is possible to confuse them. So... where's t=
hat confusion?<br><br>Java exception specifications are effectively part of=
a function's type. The compiler will detect every attempt to call a functi=
on, and it can detect if any exceptions thrown by that function leak out of=
the calling function. In that case, the calling function must explicitly d=
eclare that it emits those exceptions, or a compiler error results. This is=
propagated up the entire call-stack, until someone actually handles it.<br=
><br>All of this is just as true of propagating `expected` errors. If the e=
rror cannot be handled locally, you must keep returning the `expected` (thu=
s making it part of the function's return type) until you finally find some=
one who handles it. And, with your "pattern matching" syntax, a compiler er=
ror will result if you don't handle all of the cases.<br><br>I fail to see =
the confusion. Oh, there are differences. But they're still very comparable=
in user burden. Only `expected` is even more burdensome.<br><br></div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;">That said, an "arbitrary callable"=
that has an unconstrained interface
<br>(it can throw anything it wants) sounds like a design failure to me.
<br>Certainly you're documenting and constraining _which_ exceptions an
<br>"arbitrary" callee can throw so you know which exceptions to actually
<br>catch, yes? I'd almost definitely make any event library explicitly
<br>only work with noexcept(true) functions and pray that N4533 gets
<br>accepted. <br></blockquote><div><br>... That is patently absurd. Why do=
es a generic event system need to know or care about what specific errors p=
ass between the code emitting the error and the code consuming it? It's not=
handling those errors; it <i>can't</i> handle those errors. Those errors r=
epresent a failure of the called process to complete. The event system is p=
rocess-agnostic (generally speaking), so it lacks sufficient knowledge or a=
bility to actually do anything other than pass the error along.<br><br>So w=
hy spend the syntax to do so?<br><br>Forget an "event" system; just conside=
r std::transform. You pass it a functor, and it's going to call that functo=
r, storing each value in the output iterator.<br><br>If that process can er=
ror... how do you handle that with `expected`? Do you specialize `std::tran=
sform` based on the return type of the functor's operator(), with a special=
implementation if it returns an `expected`? Or does it just store the `exp=
ected` object in the output, thus forcing your output iterator to be able t=
o accept that and error test accordingly?<br><br>With an exception, this is=
trivial; your functor throws. This halts the process and returns various i=
nformation. Sadly, you can't get exactly where you are in the list, but you=
at least left `transform` and returned to reasonable code.<br><br>What if =
incrementing the iterator causes an error? Does `std::transform` have to be=
written to have ++ return an `expected`? With exceptions, it is understood=
how you handle this; with `expected`, it simply doesn't work.<br><br>`expe=
cted` works in the case of static, human-written function calls; in the cas=
e of dynamic ones, whether runtime polymorphism or compiletime, it has prob=
lems.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">>>
<br>>> and in a way that does not automatically require calling funct=
ions to
<br>>> adjust if they just pass the error through thanks to
<br>>> auto-return-type-deduction and the above try-expression syntax=
..
<br>>
<br>>
<br>> Not everyone can use auto-return-type-deduction or calling into so=
me other
<br>> context to resolve problems. Not everyone sticks all their code in=
to
<br>> headers, you know.
<br>
<br>... Said to the guy who's literally in the tail end of weeks-long
<br>process of ripping out every single last near-pointless use of Boost
<br>from a ~2 million line game engine and tool suite "just" to gain a ~5%
<br>build time improvement and ~15% debug binary size reduction. :p
<br>
<br>That said, no, of course we don't all put code in headers. That's not
<br>super relevant to the discussion, is it?<br></blockquote><div><br>Ahem:=
"...in a way that does not automatically require calling functions to
adjust if they just pass the error through thanks to <b>auto-return-type-de=
duction</b>..."<br><br>You can't have auto-return-type-deduction if the fun=
ction body isn't locally available to the translation unit. So for most cod=
e, that means "in headers". And without auto-return-type-deduction, you can=
't have "a way that does not automatically require calling functions to
adjust if they just pass the error through." Those functions will have to e=
xplicitly name the errors being passed through in their return types.<br><b=
r>Modules may make it so that we'll all be using auto-return-type-deduction=
.. But until then...<br><br></div><blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;">
> And since there's no syntax that will cause a failure of some kind if =
you
<br>> don't check for a particular type of error, it is very easy to mis=
s a
<br>> specific case without anyone realizing. So this is not better than
<br>> exceptions in any way. Indeed, it's worse; at least with exception=
s, you
<br>> either catch it or halt. This way, you catch it or... the program =
just keeps
<br>> going.
<br>
<br>Most languages with pattern matching actually require you to handle
<br>all cases, or explicitly add in the default case (akin to catching an
<br>exception and ignoring it). Most C++ compilers already do this today
<br>in switch-statements with a warning. One would expect a quality
<br>extension to C++ for pattern matching to follow suit.<br></blockquote><=
div><br>Yes. And this "pattern matching" will be <i>optional</i>, not manda=
tory. Certainly, there has been no proposal about it; the current `expected=
` proposal certainly isn't suggesting anything but a library change. So `ex=
pected` cannot be written to assume that it exists.<br><br>And quite frankl=
y, I don't think a lot of people will appreciate having to basically write =
try/catch blocks to handle `expected`. To my mind, and that of many others =
I imagine, `expected` exists to <i>avoid</i> that. Which is basically my po=
int: you keep trying to use `expected` to handle situations that it's just =
not intended to handle. It's really good at <i>local</i> error handling. Ad=
ding a bunch of features to help it in non-local scenarios is simply using =
the wrong tool for the job.<br><br>Exceptions are a sledgehammer; expected =
is a scalpel. Both are good tools in their domain, yet you seem to be promo=
ting the idea that everyone should become a surgeon.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_43_2116702271.1433401251667--
------=_Part_42_2083467458.1433401251667--
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Thu, 4 Jun 2015 11:02:38 +0200
Raw View
> Il giorno 03/giu/2015, alle ore 23:01, Nicol Bolas <jmckesson@gmail.com> =
ha scritto:
>=20
> Agreed.
>=20
>=20
> You... do? The entire rest of your post seems to disagree.
>=20
You=E2=80=99re right, I should have replied with more details on the three =
points
> That all brings me to a number of conclusions:
>=20
> 1) Exceptions work best in non-local error handling contexts. Local error=
handling best works via `expected`, except where `expected` cannot be used=
or is poor at the job.
>=20
I believe what you call =E2=80=9Cnon local=E2=80=9D is what I=E2=80=99d rec=
ognize as a consequence of the presence of IO actions
and thus we agree that nonlocal errors are best handled with exceptions.
Everything else is =E2=80=9Clocal=E2=80=9D in the sense that, in the spirit=
of striving to have as much total pure functions as possible,
I don=E2=80=99t want to make my functions to affect anything other than the=
ir return values and (since we=E2=80=99re in C++) some controlled and
precisely defined piece of state (for example the object instance of a memb=
er function call).
In that sense I agree with your dichotomy: exceptions for out-of-band error=
reporting, and expected (or optional) to just=20
locally represent the absence of a return value (e.g. turning a partial fun=
ction into a total one by adding an element to its range)
> 2) The difference between local and non-local handling cannot be known to=
the library. It may guess and hope, but there are usually legitimate cases=
where a user might handle errors one way or the other.
>=20
There are always legitimate cases where the user could want to do anything.
Even in Haskell there are legitimate cases to break purity using unsafePerf=
ormIO,
so I don=E2=80=99t think we can talk about C++ without taking into account =
the corner cases.
The language should encourage best practices, and make bad practices to req=
uire
explicit action, but not make them truly impossible.
> 3) Where possible, allow the user to decide whether errors are handled lo=
cally or not. As such, functions that error should have two versions: one t=
hat throws and one that uses `expected`.
>=20
> You all but stated that having a parsing system throw exceptions was a pr=
iori the wrong way to deal with them.
>=20
> And yet, you agree that libraries, including parsing libraries, should of=
fer both interfaces where possible? Why do you agree with that?
This is not a general design principle. I certainly won=E2=80=99t implement=
a throwing parsing routine in my code.
But we=E2=80=99re talking about the standard library here, and the world is=
not only parsing.
Also please remember that even if I=E2=80=99d ideally use exceptions for IO=
code (like in the Filesystem TS), there are a great
number of places where exceptions cannot be used at all (and outright disab=
led). One could argue
that disabling exceptions is not a standard-conforming action, but the real=
ity is that it happens _a lot_ in practice.
From the standard library point of view, it=E2=80=99s bad to report error _=
only_ via an interface that=E2=80=99s disabled 50% of
the time. For reporting out-of-memory exceptions or out of bounds indexes w=
e can make it with asserts instead,
but the Filesystem TS does a kind of thing (dealing with files) where you _=
have_ to deal with errors. You can=E2=80=99t
simply crash if the file the user wants cannot be read. So it=E2=80=99s man=
datory to offer a non throwing interface, to let
users use the library even if they cannot use exception. In this sense, mak=
e the user chose which interface to use
is perfectly a good thing, at least in the Standard Library, and using expe=
cted is certainly a better option
than error codes passed by reference. What I don=E2=80=99t agree is to use =
_only_ expected as the only way to report
errors in the Filesystem TS, for the reasons I already outlined.
> To me, you post made the following points: You stated that expected is th=
e right way to handle most errors, defending this with arguments from the f=
unctional programming world. The only errors you conceded ought to be handl=
ed by exeptions were either those cases where `expected` can't work or I/O,=
which functional programming handles a different way. You believe so stron=
gly in `expected` in point of fact that you want to add special syntax to t=
he language just to support the construct more fully (alterations to `await=
`, presumably based on some generic interface. Because that worked out so w=
ell for range-based for).
I would lastly point out that the special syntax is not for expected, nor f=
or optional.
Here we are going to have a full-blown monadic "do notation=E2=80=9D built =
into the language.
Everybody that has coded in Haskell a bit knows what kind of power this thi=
ng can give
to the language. The generic interface already exist in the await 2.0 propo=
sal, albeit
with naming choices that resemble its primary concurrency target. Neverthel=
ess it=E2=80=99s
general enough to work for any monadic interface, and that is very really g=
reatly
wonderful news. I suggest to any C++ coder out there to investigate what th=
is syntax
brings to the table for free once we have it, not only for error handling b=
ut also
for data manipulation (with the upcoming ranges library) and a lot more of =
other
things. There will be a great talk by Ivan Cukic at this year=E2=80=99s Mee=
ting C++ conference=20
about this topic.
>=20
> --=20
>=20
> ---=20
> You received this message because you are subscribed to the Google Groups=
"ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an=
email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at http://groups.google.com/a/isocpp.org/group/std-propo=
sals/.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Thu, 04 Jun 2015 11:04:40 -0400
Raw View
On 2015-06-04 03:00, Nicol Bolas wrote:
> Java exception specifications are effectively part of a function's type.
> The compiler will detect every attempt to call a function, and it can
> detect if any exceptions thrown by that function leak out of the calling
> function. In that case, the calling function must explicitly declare that
> it emits those exceptions, or a compiler error results. This is propagated
> up the entire call-stack, until someone actually handles it.
>
> All of this is just as true of propagating `expected` errors. If the error
> cannot be handled locally, you must keep returning the `expected` (thus
> making it part of the function's return type) until you finally find
> someone who handles it. And, with your "pattern matching" syntax, a
> compiler error will result if you don't handle all of the cases.
Since that's trivially untrue in the case that your code allows
exceptions, I guess you are talking about the case where exceptions are
forbidden. In which case, sure, that's a point, but can you propose a
better solution? Or are you just reinforcing your later point (quoted
below)?
Mind...
> Exceptions are a sledgehammer; expected is a scalpel. Both are good tools
> in their domain, yet you seem to be promoting the idea that everyone should
> become a surgeon.
....I agree with this. I think we need expected, but I don't think we
should be promoting it as the One True Method for global error handling.
Developers should continue to use their preferred method for error
propagation. As much as possible, expected should be friendly to callers
that want to turn errors into exceptions.
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Fri, 5 Jun 2015 02:35:04 -0700 (PDT)
Raw View
------=_Part_511_1332433335.1433496904112
Content-Type: multipart/alternative;
boundary="----=_Part_512_247590429.1433496904112"
------=_Part_512_247590429.1433496904112
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
2015. j=C3=BAnius 4., cs=C3=BCt=C3=B6rt=C3=B6k 0:41:24 UTC+2 id=C5=91pontba=
n Nicol Bolas a=20
k=C3=B6vetkez=C5=91t =C3=ADrta:
>
> Yeah, Java tried that with `throw` specifications. It is fairly widely=20
> agreed that this approach *sucked*.
>
Why? I mean, Google/Bing/insert_your_favorite_search_engine_here gives=20
results, but very few of them go beyond "it sucks", and those that do, they=
=20
are inconsistent, and mostly rant on the *implementation*, not the *idea*.
In C++03 standardese it sucked because of a design issue that resulted in a=
=20
big performance hit: all functions having to catch(...) and call=20
std::terminate if encountered a non-listed exception. It was "less" problem=
=20
for some compilers because they chose to ignore it (making them essentially=
=20
non-standard) apart from the empty specification, making essentially=20
throw() =3D=3D noexcept v0.9.
Robert
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_512_247590429.1433496904112
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>2015. j=C3=BAnius 4., cs=C3=BCt=C3=B6rt=C3=B6k 0:41:24=
UTC+2 id=C5=91pontban Nicol Bolas a k=C3=B6vetkez=C5=91t =C3=ADrta:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Yeah, Java trie=
d that with `throw` specifications. It is fairly widely agreed that this ap=
proach <i>sucked</i>.</div></div></blockquote><div><br>Why? I mean, Google/=
Bing/insert_your_favorite_search_engine_here gives results, but very few of=
them go beyond "it sucks", and those that do, they are inconsistent, and m=
ostly rant on the *implementation*, not the *idea*.<br><br>In C++03 standar=
dese it sucked because of a design issue that resulted in a big performance=
hit: all functions having to catch(...) and call std::terminate if encount=
ered a non-listed exception. It was "less" problem for some compilers becau=
se they chose to ignore it (making them essentially non-standard) apart fro=
m the empty specification, making essentially throw() =3D=3D noexcept v0.9.=
<br><br>Robert<br></div><mytubeelement data=3D"{"bundle":{"l=
abel_delimitor":":","percentage":"%",&qu=
ot;smart_buffer":"Smart Buffer","start_playing_when_buf=
fered":"Start playing when buffered","sound":"=
;Sound","desktop_notification":"Desktop Notification&qu=
ot;,"continuation_on_next_line":"-","loop":&q=
uot;Loop","only_notify":"Only Notify","estima=
ted_time":"Estimated Time","global_preferences":&q=
uot;Global Preferences","no_notification_supported_on_your_browse=
r":"No notification style supported on your browser version"=
,"video_buffered":"Video Buffered","buffered"=
:"Buffered","hyphen":"-","buffered_messa=
ge":"The video has been buffered as requested and is ready to pla=
y.","not_supported":"Not Supported","on"=
:"On","off":"Off","click_to_enable_for_t=
his_site":"Click to enable for this site","desktop_noti=
fication_denied":"You have denied permission for desktop notifica=
tion for this site","notification_status_delimitor":";&=
quot;,"error":"Error","adblock_interferance_messag=
e":"Adblock (or similar extension) is known to interfere with Sma=
rtVideo. Please add this url to adblock whitelist.","calculating&=
quot;:"Calculating","waiting":"Waiting","=
;will_start_buffering_when_initialized":"Will start buffering whe=
n initialized","will_start_playing_when_initialized":"W=
ill start playing when initialized","completed":"Comple=
ted","buffering_stalled":"Buffering is stalled. Will st=
op.","stopped":"Stopped","hr":"Hr&q=
uot;,"min":"Min","sec":"Sec","=
any_moment":"Any Moment","popup_donate_to":"D=
onate to","extension_id":null},"prefs":{"desk=
topNotification":true,"soundNotification":false,"logLev=
el":0,"enable":true,"loop":false,"hidePopup&q=
uot;:true,"autoPlay":false,"autoBuffer":true,"auto=
PlayOnBuffer":true,"autoPlayOnBufferPercentage":42,"aut=
oPlayOnSmartBuffer":true,"quality":"hd720","f=
shd":true,"onlyNotification":false,"enableFullScreen&qu=
ot;:true,"saveBandwidth":true,"hideAnnotations":true,&q=
uot;turnOffPagedBuffering":true}}" event=3D"preferencesUpdated" id=3D"=
myTubeRelayElementToPage"></mytubeelement><mytubeelement data=3D"{"loa=
dBundle":true}" event=3D"relayPrefs" id=3D"myTubeRelayElementToTab"></=
mytubeelement></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_512_247590429.1433496904112--
------=_Part_511_1332433335.1433496904112--
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Fri, 5 Jun 2015 14:34:18 +0200
Raw View
--Apple-Mail=_26FAAA0D-E798-4D9D-9309-650BB750A7A6
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> Il giorno 05/giu/2015, alle ore 11:35, R=C3=B3bert D=C3=A1vid <lrdxgm@gma=
il.com> ha scritto:
>=20
>=20
> 2015. j=C3=BAnius 4., cs=C3=BCt=C3=B6rt=C3=B6k 0:41:24 UTC+2 id=C5=91pont=
ban Nicol Bolas a k=C3=B6vetkez=C5=91t =C3=ADrta:
> Yeah, Java tried that with `throw` specifications. It is fairly widely ag=
reed that this approach sucked.
>=20
> Why? I mean, Google/Bing/insert_your_favorite_search_engine_here gives re=
sults, but very few of them go beyond "it sucks", and those that do, they a=
re inconsistent, and mostly rant on the *implementation*, not the *idea*.
>=20
> In C++03 standardese it sucked because of a design issue that resulted in=
a big performance hit: all functions having to catch(...) and call std::te=
rminate if encountered a non-listed exception. It was "less" problem for so=
me compilers because they chose to ignore it (making them essentially non-s=
tandard) apart from the empty specification, making essentially throw() =3D=
=3D noexcept v0.9.
>=20
The main problem of Java exception specifications is not exception specific=
ations themselves, imho.
The problem is that exceptions are the default and only error mechanism use=
d in the Java world
(besides returning null objects), and the syntax is not convenient enough f=
or this heavy usage.
In my opinion it is good to use the type system to _force_ the caller to ha=
ndle the error
(even if just to explicitly ignore it).
That=E2=80=99s the best practice in the strongly typed functional programmi=
ng world, and that=E2=80=99s what
expected would achieve (in contrast to C++03 exception specifications which=
were handled _at runtime_).
The problem with Java checked exceptions is that the syntax simply is not u=
p to the task.
Every time you call a function, and you don=E2=80=99t want to propagate the=
error to your caller,
you have to add a try {}catch{} block. This disrupt the control flow: what =
if you need to do
something different depending on the success of the call? instead of a simp=
le branch you have
to do one thing immediately after the call and another thing in a _whole ot=
her code block_.
What if the recovery code is the same among a few calls? you can catch mult=
iple exceptions
of the same type in the same catch{} block, but then you cannot discriminat=
e who raised the exception.
At the end, the mechanism is only a burden to the programmer, makes the cal=
ling code less readable,
and folks just make their exceptions unchecked exceptions (those that you d=
on=E2=80=99t have to add to the
exceptions list) or end up wrapping all the function code with an empty cat=
ch{} block. Useless=E2=80=A6
If the language had an optional/expected-style way to signal the _absence o=
f a return value_, and the
libraries consistently used that instead of exceptions for that task, relyi=
ng on exceptions to
only signal _exceptional_ situations (like IO failures), the whole checked =
exception mechanism would
be great and useful.
Note that expected-style error handling also needs good syntax to be effect=
ively used and not
incur in the same problems: that=E2=80=99s why I advocate it for C++ only n=
ow that we=E2=80=99ll have the monadic
'do notation' provided by the await 2.0 proposal.
> Robert
Bye,
Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_26FAAA0D-E798-4D9D-9309-650BB750A7A6
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">Il giorno 05/giu/201=
5, alle ore 11:35, R=C3=B3bert D=C3=A1vid <<a href=3D"mailto:lrdxgm@gmai=
l.com" class=3D"">lrdxgm@gmail.com</a>> ha scritto:</div><br class=3D"Ap=
ple-interchange-newline"><div class=3D""><div dir=3D"ltr" class=3D""><br cl=
ass=3D"">2015. j=C3=BAnius 4., cs=C3=BCt=C3=B6rt=C3=B6k 0:41:24 UTC+2 id=C5=
=91pontban Nicol Bolas a k=C3=B6vetkez=C5=91t =C3=ADrta:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr" class=3D""><div class=3D"">Yea=
h, Java tried that with `throw` specifications. It is fairly widely agreed =
that this approach <i class=3D"">sucked</i>.</div></div></blockquote><div c=
lass=3D""><br class=3D"">Why? I mean, Google/Bing/insert_your_favorite_sear=
ch_engine_here gives results, but very few of them go beyond "it sucks", an=
d those that do, they are inconsistent, and mostly rant on the *implementat=
ion*, not the *idea*.<br class=3D""><br class=3D"">In C++03 standardese it =
sucked because of a design issue that resulted in a big performance hit: al=
l functions having to catch(...) and call std::terminate if encountered a n=
on-listed exception. It was "less" problem for some compilers because they =
chose to ignore it (making them essentially non-standard) apart from the em=
pty specification, making essentially throw() =3D=3D noexcept v0.9.<br clas=
s=3D""><br class=3D""></div></div></div></blockquote><div><br class=3D""></=
div><div>The main problem of Java exception specifications is not exception=
specifications themselves, imho.</div><div>The problem is that exceptions =
are the default and only error mechanism used in the Java world</div><div>(=
besides returning null objects), and the syntax is not convenient enough fo=
r this heavy usage.</div><div><br class=3D""></div><div>In my opinion it is=
good to use the type system to _force_ the caller to handle the error</div=
><div>(even if just to explicitly ignore it).</div><div>That=E2=80=99s the =
best practice in the strongly typed functional programming world, and that=
=E2=80=99s what</div><div>expected would achieve (in contrast to C++03 exce=
ption specifications which were handled _at runtime_).</div><div><br class=
=3D""></div><div>The problem with Java checked exceptions is that the synta=
x simply is not up to the task.</div><div>Every time you call a function, a=
nd you don=E2=80=99t want to propagate the error to your caller,</div><div>=
you have to add a try {}catch{} block. This disrupt the control flow: what =
if you need to do</div><div>something different depending on the success of=
the call? instead of a simple branch you have</div><div>to do one thing im=
mediately after the call and another thing in a _whole other code block_.</=
div><div>What if the recovery code is the same among a few calls? you can c=
atch multiple exceptions</div><div>of the same type in the same catch{} blo=
ck, but then you cannot discriminate who raised the exception.</div><div><b=
r class=3D""></div><div>At the end, the mechanism is only a burden to the p=
rogrammer, makes the calling code less readable,</div><div>and folks just m=
ake their exceptions unchecked exceptions (those that you don=E2=80=99t hav=
e to add to the</div><div>exceptions list) or end up wrapping all the funct=
ion code with an empty catch{} block. Useless=E2=80=A6</div><div><br class=
=3D""></div><div>If the language had an optional/expected-style way to sign=
al the _absence of a return value_, and the</div><div>libraries consistentl=
y used that instead of exceptions for that task, relying on exceptions to</=
div><div>only signal _exceptional_ situations (like IO failures), the whole=
checked exception mechanism would</div><div>be great and useful.</div><div=
><br class=3D""></div><div>Note that expected-style error handling also nee=
ds good syntax to be effectively used and not</div><div>incur in the same p=
roblems: that=E2=80=99s why I advocate it for C++ only now that we=E2=80=99=
ll have the monadic</div><div>'do notation' provided by the await 2.0 propo=
sal.</div><div><br class=3D""></div><blockquote type=3D"cite" class=3D""><d=
iv class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">Robert<br class=
=3D""></div><mytubeelement data=3D"{"bundle":{"label_delimit=
or":":","percentage":"%","smart_buf=
fer":"Smart Buffer","start_playing_when_buffered":=
"Start playing when buffered","sound":"Sound"=
,"desktop_notification":"Desktop Notification","co=
ntinuation_on_next_line":"-","loop":"Loop&quo=
t;,"only_notify":"Only Notify","estimated_time&quo=
t;:"Estimated Time","global_preferences":"Global P=
references","no_notification_supported_on_your_browser":&quo=
t;No notification style supported on your browser version","video=
_buffered":"Video Buffered","buffered":"Buffe=
red","hyphen":"-","buffered_message":&qu=
ot;The video has been buffered as requested and is ready to play.",&qu=
ot;not_supported":"Not Supported","on":"On&qu=
ot;,"off":"Off","click_to_enable_for_this_site&quo=
t;:"Click to enable for this site","desktop_notification_den=
ied":"You have denied permission for desktop notification for thi=
s site","notification_status_delimitor":";","=
error":"Error","adblock_interferance_message":&quo=
t;Adblock (or similar extension) is known to interfere with SmartVideo. Ple=
ase add this url to adblock whitelist.","calculating":"=
Calculating","waiting":"Waiting","will_start_=
buffering_when_initialized":"Will start buffering when initialize=
d","will_start_playing_when_initialized":"Will start pl=
aying when initialized","completed":"Completed",&q=
uot;buffering_stalled":"Buffering is stalled. Will stop.",&q=
uot;stopped":"Stopped","hr":"Hr","m=
in":"Min","sec":"Sec","any_moment&q=
uot;:"Any Moment","popup_donate_to":"Donate to&quo=
t;,"extension_id":null},"prefs":{"desktopNotificat=
ion":true,"soundNotification":false,"logLevel":0,&=
quot;enable":true,"loop":false,"hidePopup":true,&q=
uot;autoPlay":false,"autoBuffer":true,"autoPlayOnBuffer=
":true,"autoPlayOnBufferPercentage":42,"autoPlayOnSmart=
Buffer":true,"quality":"hd720","fshd":tr=
ue,"onlyNotification":false,"enableFullScreen":true,&qu=
ot;saveBandwidth":true,"hideAnnotations":true,"turnOffP=
agedBuffering":true}}" event=3D"preferencesUpdated" id=3D"myTubeRelayE=
lementToPage" class=3D""></mytubeelement><mytubeelement data=3D"{"load=
Bundle":true}" event=3D"relayPrefs" id=3D"myTubeRelayElementToTab" cla=
ss=3D""></mytubeelement></div></div></blockquote><br class=3D""></div><div>=
Bye,</div><div>Nicola</div><br class=3D""></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_26FAAA0D-E798-4D9D-9309-650BB750A7A6--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 5 Jun 2015 09:01:22 -0700 (PDT)
Raw View
------=_Part_1263_130719500.1433520082761
Content-Type: multipart/alternative;
boundary="----=_Part_1264_126865619.1433520082761"
------=_Part_1264_126865619.1433520082761
Content-Type: text/plain; charset=UTF-8
On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew Woehlke wrote:
>
> On 2015-06-04 03:00, Nicol Bolas wrote:
> > Exceptions are a sledgehammer; expected is a scalpel. Both are good
> tools
> > in their domain, yet you seem to be promoting the idea that everyone
> should
> > become a surgeon.
>
> ...I agree with this. I think we need expected, but I don't think we
> should be promoting it as the One True Method for global error handling.
> Developers should continue to use their preferred method for error
> propagation. As much as possible, expected should be friendly to callers
> that want to turn errors into exceptions.
>
You were doing so well, right up until the last sentence.
The choice needs to be made by the caller, yes. But the choice should be
made by calling a function that throws exceptions, not by calling some
member of an `expected`. By then, you've already lost some information that
the function had about the actual error.
Oh, you can have `.value()` throw if it doesn't hold a value; that's fine.
But throwing in such a case should not represent the same thing as the
function actually throwing. It instead represents a caller of the
`expected` version who didn't do what he was supposed to do.
APIs should provide both, not simply rely on `expected` to throw for users
who want exceptions.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1264_126865619.1433520082761
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Ma=
tthew Woehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2015-06=
-04 03:00, Nicol Bolas wrote:
<br>> Exceptions are a sledgehammer; expected is a scalpel. Both are goo=
d tools=20
<br>> in their domain, yet you seem to be promoting the idea that everyo=
ne should=20
<br>> become a surgeon.
<br>
<br>...I agree with this. I think we need expected, but I don't think we
<br>should be promoting it as the One True Method for global error handling=
..
<br>Developers should continue to use their preferred method for error
<br>propagation. As much as possible, expected should be friendly to caller=
s
<br>that want to turn errors into exceptions.<br></blockquote><div><br>You =
were doing so well, right up until the last sentence.<br></div><br>The choi=
ce needs to be made by the caller, yes. But the choice should be made by ca=
lling a function that throws exceptions, not by calling some member of an `=
expected`. By then, you've already lost some information that the function =
had about the actual error.<br><br>Oh, you can have `.value()` throw if it =
doesn't hold a value; that's fine. But throwing in such a case should not r=
epresent the same thing as the function actually throwing. It instead repre=
sents a caller of the `expected` version who didn't do what he was supposed=
to do.<br><br>APIs should provide both, not simply rely on `expected` to t=
hrow for users who want exceptions.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1264_126865619.1433520082761--
------=_Part_1263_130719500.1433520082761--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 5 Jun 2015 09:36:44 -0700 (PDT)
Raw View
------=_Part_370_2093718160.1433522204730
Content-Type: multipart/alternative;
boundary="----=_Part_371_1635480255.1433522204737"
------=_Part_371_1635480255.1433522204737
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigante wrote:
>
> Il giorno 05/giu/2015, alle ore 11:35, R=C3=B3bert D=C3=A1vid <lrd...@gma=
il.com=20
> <javascript:>> ha scritto:
>
>
> 2015. j=C3=BAnius 4., cs=C3=BCt=C3=B6rt=C3=B6k 0:41:24 UTC+2 id=C5=91pont=
ban Nicol Bolas a=20
> k=C3=B6vetkez=C5=91t =C3=ADrta:
>>
>> Yeah, Java tried that with `throw` specifications. It is fairly widely=
=20
>> agreed that this approach *sucked*.
>>
>
> Why? I mean, Google/Bing/insert_your_favorite_search_engine_here gives=20
> results, but very few of them go beyond "it sucks", and those that do, th=
ey=20
> are inconsistent, and mostly rant on the *implementation*, not the *idea*=
..
>
> In C++03 standardese it sucked because of a design issue that resulted in=
=20
> a big performance hit: all functions having to catch(...) and call=20
> std::terminate if encountered a non-listed exception. It was "less" probl=
em=20
> for some compilers because they chose to ignore it (making them essential=
ly=20
> non-standard) apart from the empty specification, making essentially=20
> throw() =3D=3D noexcept v0.9.
>
>
> The main problem of Java exception specifications is not exception=20
> specifications themselves, imho.
> The problem is that exceptions are the default and only error mechanism=
=20
> used in the Java world
> (besides returning null objects), and the syntax is not convenient enough=
=20
> for this heavy usage.
>
> In my opinion it is good to use the type system to _force_ the caller to=
=20
> handle the error
> (even if just to explicitly ignore it).
> That=E2=80=99s the best practice in the strongly typed functional program=
ming=20
> world,
>
I'm sure it is.
So what?
C++ is not a functional language, nor is it going to become one in the near=
=20
future. What happens in "the strongly typed functional programming world"=
=20
is all well and good... for that world. But that *alone* doesn't make it=20
good for C++ or any other world.
You need to justify this with something more than "this is how things work=
=20
in functional programming monad pattern matching."
We don't have lambda expressions because they're useful "in functional=20
programming"; we have them because it's useful to be able to, quickly and=
=20
easily, pass stateful functions to various APIs in C++. Similarly, we=20
shouldn't have `expected` because it's how error handling is done "in=20
functional programming". We should have it because it offers up a very=20
useful option for handling errors locally in C++, solving a number of=20
problems associated with returning error codes.
You should not try to turn `expected` into full-frontal "functional=20
programming error handling." Ditch the "monads" and "pattern matching" and=
=20
so forth; just focus on the basic proposal: a return type that is both=20
error code and value.
and that=E2=80=99s what
> expected would achieve (in contrast to C++03 exception specifications=20
> which were handled _at runtime_).
>
> The problem with Java checked exceptions is that the syntax simply is not=
=20
> up to the task.
> Every time you call a function, and you don=E2=80=99t want to propagate t=
he error=20
> to your caller,
> you have to add a try {}catch{} block. This disrupt the control flow: wha=
t=20
> if you need to do
> something different depending on the success of the call? instead of a=20
> simple branch you have
>
to do one thing immediately after the call and another thing in a _whole=20
> other code block_.
> What if the recovery code is the same among a few calls? you can catch=20
> multiple exceptions
> of the same type in the same catch{} block, but then you cannot=20
> discriminate who raised the exception.
>
Note that there are folks in this thread suggesting that something like=20
this be (eventually) allowed:
expected.when {
case good (auto value) { use value; }
case failed (auto error) { handle error; }
}
That looks an awful lot like a catch block. It seems to "disrupt the=20
control flow" of the program.
It certainly pokes you in the eye a lot.
It seems to me that not everyone agrees with you that one is particularly=
=20
different from the other.
Also, with regard to your question of "What if the recovery code is the=20
same among a few calls?", `expected` doesn't exactly solve that one either.=
=20
If you have two functions that return two `expected` objects, you still=20
have to test each one in turn.
Also, if the recovery code "is the same among a few calls", you don't *need=
*=20
to discriminate between them. Not unless they're using different values=20
that are specific to each call. And even that is solved by simply=20
extracting the identical code into a function, that gets called with the=20
parameters it needs.
And again, `expected` doesn't solve that either. If the code uses different=
=20
values that are specific to each error's cause, you still need to extract=
=20
the code into functions and use parameters on them.
Note that expected-style error handling also needs good syntax to be=20
> effectively used and not
> incur in the same problems: that=E2=80=99s why I advocate it for C++ only=
now that=20
> we=E2=80=99ll have the monadic
> 'do notation' provided by the await 2.0 proposal.
>
What "await 2.0 proposal" are you referring to? What 'do notation'? I don't=
=20
see anything like this in N4499.
Also, something will seriously be wrong in C++ if this becomes legitimate=
=20
error handling syntax:
auto b =3D (await (await a).foo()).bar();
When I look at this, I see syntax that says "stop here until this=20
completes", not syntax that says, "handle errors that are returned by this=
=20
expression." Using the former for the *sole purpose* of achieving the=20
latter is a brutal language hack, not good syntax.
If you want to have syntax for dealing with `expected` more easily, then=20
propose that. But don't hijack a perfectly good coroutine proposal just to=
=20
graft `expected`-based error handling onto it. Make it a separate=20
construct, rather than some kind of Congressional rider amendment that's=20
attached to a must-pass budget appropriations bill.
That's just disingenuous.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_371_1635480255.1433522204737
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigant=
e wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wra=
p:break-word"><div><blockquote type=3D"cite"><div>Il giorno 05/giu/2015, al=
le ore 11:35, R=C3=B3bert D=C3=A1vid <<a href=3D"javascript:" target=3D"=
_blank" gdf-obfuscated-mailto=3D"g7ugSvb9uvoJ" rel=3D"nofollow" onmousedown=
=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">lrd...@gmail.com</a>> ha scritto:</div><br><div><div=
dir=3D"ltr"><br>2015. j=C3=BAnius 4., cs=C3=BCt=C3=B6rt=C3=B6k 0:41:24 UTC=
+2 id=C5=91pontban Nicol Bolas a k=C3=B6vetkez=C5=91t =C3=ADrta:<blockquote=
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px =
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Yeah, Java tried that wi=
th `throw` specifications. It is fairly widely agreed that this approach <i=
>sucked</i>.</div></div></blockquote><div><br>Why? I mean, Google/Bing/inse=
rt_your_<wbr>favorite_search_engine_here gives results, but very few of the=
m go beyond "it sucks", and those that do, they are inconsistent, and mostl=
y rant on the *implementation*, not the *idea*.<br><br>In C++03 standardese=
it sucked because of a design issue that resulted in a big performance hit=
: all functions having to catch(...) and call std::terminate if encountered=
a non-listed exception. It was "less" problem for some compilers because t=
hey chose to ignore it (making them essentially non-standard) apart from th=
e empty specification, making essentially throw() =3D=3D noexcept v0.9.<br>=
<br></div></div></div></blockquote><div><br></div><div>The main problem of =
Java exception specifications is not exception specifications themselves, i=
mho.</div><div>The problem is that exceptions are the default and only erro=
r mechanism used in the Java world</div><div>(besides returning null object=
s), and the syntax is not convenient enough for this heavy usage.</div><div=
><br></div><div>In my opinion it is good to use the type system to _force_ =
the caller to handle the error</div><div>(even if just to explicitly ignore=
it).</div><div>That=E2=80=99s the best practice in the strongly typed func=
tional programming world,</div></div></div></blockquote><div><br>I'm sure i=
t is.<br><br>So what?<br><br>C++ is not a functional language, nor is it go=
ing to become one in the near future. What happens in "the strongly typed f=
unctional programming world" is all well and good... for that world. But th=
at <i>alone</i> doesn't make it good for C++ or any other world.<br><br>You=
need to justify this with something more than "this is how things work in =
functional programming monad pattern matching."<br><br>We don't have lambda=
expressions because they're useful "in functional programming"; we have th=
em because it's useful to be able to, quickly and easily, pass stateful fun=
ctions to various APIs in C++. Similarly, we shouldn't have `expected` beca=
use it's how error handling is done "in functional programming". We should =
have it because it offers up a very useful option for handling errors local=
ly in C++, solving a number of problems associated with returning error cod=
es.<br><br>You should not try to turn `expected` into full-frontal "functio=
nal programming error handling." Ditch the "monads" and "pattern matching" =
and so forth; just focus on the basic proposal: a return type that is both =
error code and value.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div style=3D"word-wrap:break-word"><div><div> and that=E2=80=99s wha=
t</div><div>expected would achieve (in contrast to C++03 exception specific=
ations which were handled _at runtime_).</div><div><br></div><div>The probl=
em with Java checked exceptions is that the syntax simply is not up to the =
task.</div><div>Every time you call a function, and you don=E2=80=99t want =
to propagate the error to your caller,</div><div>you have to add a try {}ca=
tch{} block. This disrupt the control flow: what if you need to do</div><di=
v>something different depending on the success of the call? instead of a si=
mple branch you have</div></div></div></blockquote><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div>to do on=
e thing immediately after the call and another thing in a _whole other code=
block_.</div><div>What if the recovery code is the same among a few calls?=
you can catch multiple exceptions</div><div>of the same type in the same c=
atch{} block, but then you cannot discriminate who raised the exception.</d=
iv></div></div></blockquote><div><br>Note that there are folks in this thre=
ad suggesting that something like this be (eventually) allowed:<br><br><div=
class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); borde=
r-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-w=
rap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> expected<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">when</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">case</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> good </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> value</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">use</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> value</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">case</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> failed </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> err=
or</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> handle error</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">}</span></div></code></div><div><br></div>That looks an aw=
ful lot like a catch block. It seems to "disrupt the control flow" of the p=
rogram.<br><br>It certainly pokes you in the eye a lot.<br><br>It seems to =
me that not everyone agrees with you that one is particularly different fro=
m the other.<br><br>Also, with regard to your question of "What if the reco=
very code is the same among a few calls?", `expected` doesn't exactly solve=
that one either. If you have two functions that return two `expected` obje=
cts, you still have to test each one in turn.<br><br>Also, if the recovery =
code "is the same among a few calls", you don't <i>need</i> to discriminate=
between them. Not unless they're using different values that are specific =
to each call. And even that is solved by simply extracting the identical co=
de into a function, that gets called with the parameters it needs.<br><br>A=
nd again, `expected` doesn't solve that either. If the code uses different =
values that are specific to each error's cause, you still need to extract t=
he code into functions and use parameters on them.<br><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div>=
<div></div><div></div><div>Note that expected-style error handling also nee=
ds good syntax to be effectively used and not</div><div>incur in the same p=
roblems: that=E2=80=99s why I advocate it for C++ only now that we=E2=80=99=
ll have the monadic</div><div>'do notation' provided by the await 2.0 propo=
sal.</div></div></div></blockquote><div><br>What "await 2.0 proposal" are y=
ou referring to? What 'do notation'? I don't see anything like this in N449=
9.<br><br>Also, something will seriously be wrong in C++ if this becomes le=
gitimate error handling syntax:<br><br><div class=3D"prettyprint" style=3D"=
background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bor=
der-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D=
"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> b </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">await </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">await a</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">).</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">foo</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">()).</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">bar</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">();</span></div></code></div><br>When I look at this, I=
see syntax that says "stop here until this completes", not syntax that say=
s, "handle errors that are returned by this expression." Using the former f=
or the <i>sole purpose</i> of achieving the latter is a brutal language hac=
k, not good syntax.<br><br>If you want to have syntax for dealing with `exp=
ected` more easily, then propose that. But don't hijack a perfectly good co=
routine proposal just to graft `expected`-based error handling onto it. Mak=
e it a separate construct, rather than some kind of Congressional rider ame=
ndment that's attached to a must-pass budget appropriations bill.<br><br>Th=
at's just disingenuous.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_371_1635480255.1433522204737--
------=_Part_370_2093718160.1433522204730--
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Fri, 05 Jun 2015 13:40:11 -0400
Raw View
On 2015-06-05 12:01, Nicol Bolas wrote:
> On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew Woehlke wrote:
>> I think we need expected, but I don't think we should be promoting
>> it as the One True Method for global error handling. Developers
>> should continue to use their preferred method for error
>> propagation. As much as possible, expected should be friendly to
>> callers that want to turn errors into exceptions.
>
> You were doing so well, right up until the last sentence.
So we should *not* make expected as friendly as possible for callers
that are going to turn it into an exception?
> The choice needs to be made by the caller, yes. But the choice should be
> made by calling a function that throws exceptions, not by calling some
> member of an `expected`. By then, you've already lost some information that
> the function had about the actual error.
Why? Why does returning an expected necessarily mean that information
*must* be lost?
As usual, I think you are missing the point. *If and where* expected can
be used without losing information, is there still a strong motivation
to have a throwing variant? (Why? To save a few keystrokes?) And in such
cases, should we not try to make expected as friendly as possible for
users that want exceptions?
> Oh, you can have `.value()` throw if it doesn't hold a value; that's fine.
> But throwing in such a case should not represent the same thing as the
> function actually throwing. It instead represents a caller of the
> `expected` version who didn't do what he was supposed to do.
Again, why? My understanding is that it is intended that expected be
usable by callers that just want exceptions, by simply assuming that the
expected always has a value. Yes, the exact point at which the exception
is thrown is changed (trivially), but I fail to see why that should matter.
Look at it differently. Let's say I have a function:
expected<T, exception_ptr> foo_expected();
Let's further say that the exception is exactly what foo_throws() would
throw, i.e. no information is lost. Why should I then not write:
T foo_throws() { return foo_expected().value(); }
And further, if the above is inline, how is it in any way different from
writing at the call site:
foo().value()
....?
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 5 Jun 2015 10:44:26 -0700 (PDT)
Raw View
------=_Part_1343_1862999950.1433526266026
Content-Type: multipart/alternative;
boundary="----=_Part_1344_1128586390.1433526266026"
------=_Part_1344_1128586390.1433526266026
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, June 4, 2015 at 5:02:44 AM UTC-4, Nicola Gigante wrote:
>
>
> > Il giorno 03/giu/2015, alle ore 23:01, Nicol Bolas <jmck...@gmail.com=
=20
> <javascript:>> ha scritto:=20
> >=20
> > Agreed.=20
> >=20
> >=20
> > You... do? The entire rest of your post seems to disagree.=20
> >=20
>
> You=E2=80=99re right, I should have replied with more details on the thre=
e points=20
>
> > That all brings me to a number of conclusions:=20
> >=20
> > 1) Exceptions work best in non-local error handling contexts. Local=20
> error handling best works via `expected`, except where `expected` cannot =
be=20
> used or is poor at the job.=20
> >=20
>
> I believe what you call =E2=80=9Cnon local=E2=80=9D is what I=E2=80=99d r=
ecognize as a consequence=20
> of the presence of IO actions=20
> and thus we agree that nonlocal errors are best handled with exceptions.
>
Everything else is =E2=80=9Clocal=E2=80=9D in the sense that, in the spirit=
of striving to=20
> have as much total pure functions as possible,=20
>
I don=E2=80=99t want to make my functions to affect anything other than th=
eir=20
> return values and (since we=E2=80=99re in C++) some controlled and precis=
ely=20
> defined piece of state (for example the object instance of a member=20
> function call).=20
>
> In that sense I agree with your dichotomy: exceptions for out-of-band=20
> error reporting, and expected (or optional) to just=20
> locally represent the absence of a return value (e.g. turning a partial=
=20
> function into a total one by adding an element to its range)=20
>
What I call "non local" is exactly that: non-local. "Local" is the=20
immediate caller of a function; "non-local" is everyone else. To handle an=
=20
error locally means that the process continues on, from the perspective of=
=20
the outside world. To handle the error non-locally means that part of the=
=20
process has to stop, and control must be returned to some higher level code=
=20
to deal with it.
By these definitions, locality is defined *by the user*, not by the nature=
=20
of the error. So your arbitrary decision that IO errors are non-local is=20
wrong. It's a misinterpretation of what I'm saying, through your functional=
=20
programming lens. You want locality of error handling to be decided by a=20
fundamental property of the error in question. I am explicitly saying that=
=20
this is *wrong*; it should be decided *by the user*, not some ad-hoc rule.
> 2) The difference between local and non-local handling cannot be known to=
=20
> the library. It may guess and hope, but there are usually legitimate case=
s=20
> where a user might handle errors one way or the other.=20
> >=20
>
> There are always legitimate cases where the user could want to do=20
> anything.=20
> Even in Haskell there are legitimate cases to break purity using=20
> unsafePerformIO,=20
> so I don=E2=80=99t think we can talk about C++ without taking into accoun=
t the=20
> corner cases.=20
> The language should encourage best practices, and make bad practices to=
=20
> require=20
> explicit action, but not make them truly impossible.
>
You're still missing my point. You are unilaterally deciding that IO errors=
=20
ought to be exceptions and parse errors ought to be `expected`. The point=
=20
of my conclusion #2 is that *the API has no right to make that decision for=
=20
the user*.
Consider the following. I'm building a system that writes video data. And I=
=20
have to support outdated filesystems that have maximum file sizes. Which=20
means that I write to a file until I can't write anymore, then create a new=
=20
file and write to that. The way to do that is to attempt to expand the=20
file's size when writing the next block of data. If the file's size cannot=
=20
be expanded, then I open a new file and write to that. This all happens in=
=20
a loop.
For me, an error in expanding the file's size is, um, expected; it is not=
=20
an exceptional circumstance. I ought to be able to use an `expected`=20
interface or some other local error handling mechanism (since expanding a=
=20
file's size probably doesn't return a value), rather than an=20
exception-based one. Yes, other IO errors (creating new files, writing the=
=20
actual data) will probably be exceptions that have to stop the whole=20
process.
But why deny the proper error handling mechanism for this case? Why should=
=20
the user be denied the choice?
This is why trying to graft functional programming nonsense into C++ is a=
=20
bad idea. Functional programming makes a distinction between IO errors and=
=20
other errors because it ultimately has no choice. The very idea of=20
input/output is decidedly outside the scope of the functional model. Thus,=
=20
allowing functional programming to work with input/output requires breaking=
=20
that model. Because these operations work outside of the functional model,=
=20
errors reported through them cannot be handled in the usual functional way=
=20
of handling errors. Therefore, it must use something else.
C++ is not a functional language, nor should it become one. C++ is more=20
free-form in terms of programming style, and it should not adopt constructs=
=20
that force you into decisions like this. Where you have to use exceptions=
=20
in some circumstance, because to do otherwise breaks the box you've=20
deliberately chosen to live within.
If you want to live inside the functional programming box, if you want to=
=20
decide to handle all IO errors as exceptions, fine. But don't force the=20
rest of us in there with you.
=20
> > 3) Where possible, allow the user to decide whether errors are handled=
=20
> locally or not. As such, functions that error should have two versions: o=
ne=20
> that throws and one that uses `expected`.=20
> >=20
> > You all but stated that having a parsing system throw exceptions was a=
=20
> priori the wrong way to deal with them.=20
> >=20
> > And yet, you agree that libraries, including parsing libraries, should=
=20
> offer both interfaces where possible? Why do you agree with that?=20
>
> This is not a general design principle.
Then you don't agree, because what I'm saying is that it *should be* a=20
"general design principle." For all error types, all things being equal,=20
both should be allowed. I say this not to support !C++ users who turn off=
=20
exception handling, not to support functional-programming-in-C++ users. But=
=20
simply to allow C++ programmers of all kinds to determine how best to=20
handle each individual error: locally or non-locally.
It is just not a choice that an API has the right to make.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1344_1128586390.1433526266026
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, June 4, 2015 at 5:02:44 AM UTC-4, Nicola Giga=
nte wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>> Il giorno 03/giu/2015, alle ore 23:01, Nicol Bolas <<a href=3D"=
javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"7lCsBEXliXkJ" rel=
=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return true;" onclic=
k=3D"this.href=3D'javascript:';return true;">jmck...@gmail.com</a>> ha s=
critto:
<br>>=20
<br>> Agreed.
<br>>=20
<br>>=20
<br>> You... do? The entire rest of your post seems to disagree.
<br>>=20
<br>
<br>You=E2=80=99re right, I should have replied with more details on the th=
ree points
<br>
<br>> That all brings me to a number of conclusions:
<br>>=20
<br>> 1) Exceptions work best in non-local error handling contexts. Loca=
l error handling best works via `expected`, except where `expected` cannot =
be used or is poor at the job.
<br>>=20
<br>
<br>I believe what you call =E2=80=9Cnon local=E2=80=9D is what I=E2=80=99d=
recognize as a consequence of the presence of IO actions
<br>and thus we agree that nonlocal errors are best handled with exceptions=
..<br></blockquote><div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Everyth=
ing else is =E2=80=9Clocal=E2=80=9D in the sense that, in the spirit of str=
iving to have as much total pure functions as possible, <br></blockquo=
te></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"> I don=E2=80=99t=
want to make my functions to affect anything other than their=20
return values and (since we=E2=80=99re in C++) some controlled and precisel=
y defined piece of state (for example the object instance of a member funct=
ion call).
<br>
<br>In that sense I agree with your dichotomy: exceptions for out-of-band e=
rror reporting, and expected (or optional) to just=20
<br>locally represent the absence of a return value (e.g. turning a partial=
function into a total one by adding an element to its range)
<br></blockquote><div><br>What I call "non local" is exactly that: non-loca=
l.
"Local" is the immediate caller of a function; "non-local" is everyone=20
else. To handle an error locally means that the process continues on,=20
from the perspective of the outside world. To handle the error=20
non-locally means that part of the process has to stop, and control must
be returned to some higher level code to deal with it.<br><br>By these def=
initions, locality is defined <i>by the user</i>, not by the nature of the =
error. So your arbitrary decision that IO errors are non-local is wrong. It=
's a misinterpretation of what I'm saying, through your functional programm=
ing lens. You want locality of error handling to be decided by a fundamenta=
l property of the error in question. I am explicitly saying that this is <i=
>wrong</i>; it should be decided <i>by the user</i>, not some ad-hoc rule.<=
br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
> 2) The difference between local and non-local handling cannot be known=
to the library. It may guess and hope, but there are usually legitimate ca=
ses where a user might handle errors one way or the other.
<br>>=20
<br>
<br>There are always legitimate cases where the user could want to do anyth=
ing.
<br>Even in Haskell there are legitimate cases to break purity using unsafe=
PerformIO,
<br>so I don=E2=80=99t think we can talk about C++ without taking into acco=
unt the corner cases.
<br>The language should encourage best practices, and make bad practices to=
require
<br>explicit action, but not make them truly impossible.<br></blockquote><d=
iv><br>You're still missing my point. You are unilaterally deciding that IO=
errors ought to be exceptions and parse errors ought to be `expected`. The=
point of my conclusion #2 is that <i>the API has no right to make that dec=
ision for the user</i>.<br><br>Consider the following. I'm building a syste=
m that writes video data. And I have to support outdated filesystems that h=
ave maximum file sizes. Which means that I write to a file until I can't wr=
ite anymore, then create a new file and write to that. The way to do that i=
s to attempt to expand the file's size when writing the next block of data.=
If the file's size cannot be expanded, then I open a new file and write to=
that. This all happens in a loop.<br><br>For me, an error in expanding the=
file's size is, um, expected; it is not an exceptional circumstance. I oug=
ht to be able to use an `expected` interface or some other local error hand=
ling mechanism (since expanding a file's size probably doesn't return a val=
ue), rather than an exception-based one. Yes, other IO errors (creating new=
files, writing the actual data) will probably be exceptions that have to s=
top the whole process.<br><br>But why deny the proper error handling mechan=
ism for this case? Why should the user be denied the choice?<br><br>This is=
why trying to graft functional programming nonsense into C++ is a bad idea=
.. Functional programming makes a distinction between IO errors and other er=
rors because it ultimately has no choice. The very idea of input/output is =
decidedly outside the scope of the functional model. Thus, allowing functio=
nal programming to work with input/output requires breaking that model. Bec=
ause these operations work outside of the functional model, errors reported=
through them cannot be handled in the usual functional way of handling err=
ors. Therefore, it must use something else.<br><br>C++ is not a functional =
language, nor should it become one. C++ is more free-form in terms of progr=
amming style, and it should not adopt constructs that force you into decisi=
ons like this. Where you have to use exceptions in some circumstance, becau=
se to do otherwise breaks the box you've deliberately chosen to live within=
..<br><br>If you want to live inside the functional programming box, if you =
want to decide to handle all IO errors as exceptions, fine. But don't force=
the rest of us in there with you.<br> </div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;">> 3) Where possible, allow the user to decide whethe=
r errors are handled locally or not. As such, functions that error should h=
ave two versions: one that throws and one that uses `expected`.
<br>>=20
<br>> You all but stated that having a parsing system throw exceptions w=
as a priori the wrong way to deal with them.
<br>>=20
<br>> And yet, you agree that libraries, including parsing libraries, sh=
ould offer both interfaces where possible? Why do you agree with that?
<br>
<br>This is not a general design principle.</blockquote><div><br>Then you d=
on't agree, because what I'm saying is that it <i>should be</i> a "general =
design principle." For all error types, all things being equal, both should=
be allowed. I say this not to support !C++ users who turn off exception ha=
ndling, not to support functional-programming-in-C++ users. But simply to a=
llow C++ programmers of all kinds to determine how best to handle each indi=
vidual error: locally or non-locally.<br><br>It is just not a choice that a=
n API has the right to make.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1344_1128586390.1433526266026--
------=_Part_1343_1862999950.1433526266026--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 5 Jun 2015 11:13:32 -0700 (PDT)
Raw View
------=_Part_501_424784161.1433528012621
Content-Type: multipart/alternative;
boundary="----=_Part_502_1111751299.1433528012621"
------=_Part_502_1111751299.1433528012621
Content-Type: text/plain; charset=UTF-8
On Friday, June 5, 2015 at 1:40:33 PM UTC-4, Matthew Woehlke wrote:
>
> On 2015-06-05 12:01, Nicol Bolas wrote:
> > On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew Woehlke wrote:
> >> I think we need expected, but I don't think we should be promoting
> >> it as the One True Method for global error handling. Developers
> >> should continue to use their preferred method for error
> >> propagation. As much as possible, expected should be friendly to
> >> callers that want to turn errors into exceptions.
> >
> > You were doing so well, right up until the last sentence.
>
> So we should *not* make expected as friendly as possible for callers
> that are going to turn it into an exception?
>
> > The choice needs to be made by the caller, yes. But the choice should be
> > made by calling a function that throws exceptions, not by calling some
> > member of an `expected`. By then, you've already lost some information
> that
> > the function had about the actual error.
>
> Why? Why does returning an expected necessarily mean that information
> *must* be lost?
>
> As usual, I think you are missing the point. *If and where* expected can
> be used without losing information, is there still a strong motivation
> to have a throwing variant?
Yes: API consistency.
There will be APIs where exception information can be lost, and there will
be APIs were information cannot be lost. But that is effectively an
implementation detail, one that should not be visible to the user. The user
shouldn't have to know or care that this particular function throws special
exceptions.
> > Oh, you can have `.value()` throw if it doesn't hold a value; that's
> fine.
> > But throwing in such a case should not represent the same thing as the
> > function actually throwing. It instead represents a caller of the
> > `expected` version who didn't do what he was supposed to do.
>
> Again, why? My understanding is that it is intended that expected be
> usable by callers that just want exceptions, by simply assuming that the
> expected always has a value. Yes, the exact point at which the exception
> is thrown is changed (trivially), but I fail to see why that should
> matter.
>
> Look at it differently. Let's say I have a function:
>
> expected<T, exception_ptr> foo_expected();
>
> Let's further say that the exception is exactly what foo_throws() would
> throw, i.e. no information is lost. Why should I then not write:
>
> T foo_throws() { return foo_expected().value(); }
>
Because you probably lose elision in this circumstance.
And further, if the above is inline, how is it in any way different from
> writing at the call site:
>
> foo().value()
>
Because:
1) I don't have to see the syntactically useless `.value()` in my code.
2) API consistency. `foo()` throws; `foo_exp()` returns an `expected`.
Always (unless _exp doesn't make sense for a particular function).
3) Why should `foo_exp` return `exception_ptr` at all? Why should it
construct such a heavy-weight object to contain information the majority of
which the direct caller of `foo_exp` knows already? Again, going back to
Filesystem, the filesyste_error exception contains `path` parameters; why
should a Filesystem function that returns `expected` provide access to
parameters that the caller already knows?
4) `.value()` throws the `bad_expected_access<T>` template class. Which
means that's the type the user normally has to catch (when not using
`exception_ptr`). Which means that catching code needs to recognize that
the throwing code was using `expected` to do the throwing. Why should it?
As a throwing interface, `expected` is sub-optimal. And this is as it
should be. Let the caller decide by picking the proper function to call,
not by what `expected` throws.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_502_1111751299.1433528012621
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 5, 2015 at 1:40:33 PM UTC-4, Matthew Woehl=
ke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2015-06-05 12:01, =
Nicol Bolas wrote:
<br>> On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew Woehlke wr=
ote:
<br>>> I think we need expected, but I don't think we should be promo=
ting
<br>>> it as the One True Method for global error handling. Developer=
s
<br>>> should continue to use their preferred method for error=20
<br>>> propagation. As much as possible, expected should be friendly =
to
<br>>> callers that want to turn errors into exceptions.
<br>>=20
<br>> You were doing so well, right up until the last sentence.
<br>
<br>So we should *not* make expected as friendly as possible for callers
<br>that are going to turn it into an exception?
<br>
<br>> The choice needs to be made by the caller, yes. But the choice sho=
uld be=20
<br>> made by calling a function that throws exceptions, not by calling =
some=20
<br>> member of an `expected`. By then, you've already lost some informa=
tion that=20
<br>> the function had about the actual error.
<br>
<br>Why? Why does returning an expected necessarily mean that information
<br>*must* be lost?
<br>
<br>As usual, I think you are missing the point. *If and where* expected ca=
n
<br>be used without losing information, is there still a strong motivation
<br>to have a throwing variant?</blockquote><div><br>Yes: API consistency.<=
br><br>There will be APIs where exception information can be lost, and ther=
e will be APIs were information cannot be lost. But that is effectively an =
implementation detail, one that should not be visible to the user. The user=
shouldn't have to know or care that this particular function throws specia=
l exceptions.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>> Oh, you can have `.value()` throw if it doesn't hold a value; that=
's fine.=20
<br>> But throwing in such a case should not represent the same thing as=
the=20
<br>> function actually throwing. It instead represents a caller of the=
=20
<br>> `expected` version who didn't do what he was supposed to do.
<br>
<br>Again, why? My understanding is that it is intended that expected be
<br>usable by callers that just want exceptions, by simply assuming that th=
e
<br>expected always has a value. Yes, the exact point at which the exceptio=
n
<br>is thrown is changed (trivially), but I fail to see why that should mat=
ter.
<br>
<br>Look at it differently. Let's say I have a function:
<br>
<br> expected<T, exception_ptr> foo_expected(); <br></blockquot=
e><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;">
<br>Let's further say that the exception is exactly what foo_throws() would
<br>throw, i.e. no information is lost. Why should I then not write:
<br>
<br> T foo_throws() { return foo_expected().value(); }<br></blockquot=
e><div><br>Because you probably lose elision in this circumstance.<br><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;">
And further, if the above is inline, how is it in any way different from
<br>writing at the call site:
<br>
<br> foo().value()<br></blockquote><div><br>Because:<br><br>1) I don'=
t have to see the syntactically useless `.value()` in my code.<br><br>2) AP=
I consistency. `foo()` throws; `foo_exp()` returns an `expected`. Always (u=
nless _exp doesn't make sense for a particular function).<br><br>3) Why sho=
uld `foo_exp` return `exception_ptr` at all? Why should it construct such a=
heavy-weight object to contain information the majority of which the direc=
t caller of `foo_exp` knows already? Again, going back to Filesystem, the f=
ilesyste_error exception contains `path` parameters; why should a Filesyste=
m function that returns `expected` provide access to parameters that the ca=
ller already knows?<br><br>4) `.value()` throws the `bad_expected_access<=
;T>` template class. Which means that's the type the user normally has t=
o catch (when not using `exception_ptr`). Which means that catching code ne=
eds to recognize that the throwing code was using `expected` to do the thro=
wing. Why should it?<br><br>As a throwing interface, `expected` is sub-opti=
mal. And this is as it should be. Let the caller decide by picking the prop=
er function to call, not by what `expected` throws.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_502_1111751299.1433528012621--
------=_Part_501_424784161.1433528012621--
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Fri, 05 Jun 2015 14:46:35 -0400
Raw View
On 2015-06-05 14:13, Nicol Bolas wrote:
> 4) `.value()` throws the `bad_expected_access<T>` template class. Which
> means that's the type the user normally has to catch (when not using
> `exception_ptr`). Which means that catching code needs to recognize that
> the throwing code was using `expected` to do the throwing. Why should it?
See, *this* is the point I was trying to make. *Why* does it do that?
Should it not throw an exception indicative of *why* it doesn't have a
value? (In particular, if the error is itself an exception, shouldn't it
just throw that?)
At least there should be a method that does that. Perhaps even something
short, like operator*.
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 5 Jun 2015 12:19:00 -0700 (PDT)
Raw View
------=_Part_495_1375362793.1433531940526
Content-Type: multipart/alternative;
boundary="----=_Part_496_208485643.1433531940526"
------=_Part_496_208485643.1433531940526
Content-Type: text/plain; charset=UTF-8
On Friday, June 5, 2015 at 2:47:11 PM UTC-4, Matthew Woehlke wrote:
>
> On 2015-06-05 14:13, Nicol Bolas wrote:
> > 4) `.value()` throws the `bad_expected_access<T>` template class. Which
> > means that's the type the user normally has to catch (when not using
> > `exception_ptr`). Which means that catching code needs to recognize that
> > the throwing code was using `expected` to do the throwing. Why should
> it?
>
> See, *this* is the point I was trying to make. *Why* does it do that?
> Should it not throw an exception indicative of *why* it doesn't have a
> value? (In particular, if the error is itself an exception, shouldn't it
> just throw that?)
>
> At least there should be a method that does that. Perhaps even something
> short, like operator*.
>
It really comes down to how you expect to use, well, `expected`.
`expected` is for local error handling. Higher level code shouldn't have to
know about it; it should be an implementation detail to them.
But `value` throws an exception, and this is the right call. When a user
calls `value`, one of two things is true:
1) The user has previously verified that this `expected` instance contains
a value. And thus it will never throw.
2) The user has not verified that the `expected` instance contains a value.
And thus it may throw.
#2 would happen in two circumstances:
2a) a programming bug
2b) deliberate design
2c) the user wants to catch the exception thrown. This is what you're
arguing for
With 2a, the program ought to terminate, since continuing forward in the
event of an obvious programming bug is usually not a good idea.
With 2b, the user has effectively *decided* that termination is a
legitimate response to this error.
OK, so... what about static analysis tools? We already have great static
tools that can detect the use of many uninitialized values. So it's
reasonable to assume that such tools will be expanded in the face of
`optional` and `expected`, detecting when you use them without explicitly
checking that they are real values.
The purpose of this is to track down bugs caused by 2a. However, 2a is
indistinguishable from 2b and 2c. So static analysis tools will complain
about those cases. So now you'll have to invent some extraneous syntax or a
new `expected` member function or whatever, to tell static analysis tools,
"Yes, I know that I'm reading from an untested expected. Shut up about it."
Or you can just have 2b and 2c users call the throwing version of the
function. Then it's clear to everyone what the deal is.
My point is that `value` throwing is the right move, but nobody should be
catching what `value` throws. So what it throws is irrelevant, save for the
fact that it shouldn't be throwing something that could accidentally be
caught. So throwing a new type like `bad_expected_access` is the right
move. Putting the error code in there is a nice touch, but it ought to be
more or less irrelevant to users.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_496_208485643.1433531940526
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 5, 2015 at 2:47:11 PM UTC-4, Matthew Woehl=
ke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2015-06-05 14:13, =
Nicol Bolas wrote:
<br>> 4) `.value()` throws the `bad_expected_access<T>` template c=
lass. Which=20
<br>> means that's the type the user normally has to catch (when not usi=
ng=20
<br>> `exception_ptr`). Which means that catching code needs to recogniz=
e that=20
<br>> the throwing code was using `expected` to do the throwing. Why sho=
uld it?
<br>
<br>See, *this* is the point I was trying to make. *Why* does it do that?
<br>Should it not throw an exception indicative of *why* it doesn't have a
<br>value? (In particular, if the error is itself an exception, shouldn't i=
t
<br>just throw that?)
<br>
<br>At least there should be a method that does that. Perhaps even somethin=
g
<br>short, like operator*.
<br></blockquote><div><br>It really comes down to how you expect to use, we=
ll, `expected`.<br><br>`expected` is for local error handling. Higher level=
code shouldn't have to know about it; it should be an implementation detai=
l to them.<br><br>But `value` throws an exception, and this is the right ca=
ll. When a user calls `value`, one of two things is true:<br><br>1) The use=
r has previously verified that this `expected` instance contains a value. A=
nd thus it will never throw.<br><br>2) The user has not verified that the `=
expected` instance contains a value. And thus it may throw.<br><br>#2 would=
happen in two circumstances:<br><br>2a) a programming bug <br><br>2b) deli=
berate design<br><br>2c) the user wants to catch the exception thrown. This=
is what you're arguing for<br><br>With 2a, the program ought to terminate,=
since continuing forward in the event of an obvious programming bug is usu=
ally not a good idea.<br><br>With 2b, the user has effectively <i>decided</=
i> that termination is a legitimate response to this error.<br><br>OK, so..=
.. what about static analysis tools? We already have great static tools that=
can detect the use of many uninitialized values. So it's reasonable to ass=
ume that such tools will be expanded in the face of `optional` and `expecte=
d`, detecting when you use them without explicitly checking that they are r=
eal values.<br><br>The purpose of this is to track down bugs caused by 2a. =
However, 2a is indistinguishable from 2b and 2c. So static analysis tools w=
ill complain about those cases. So now you'll have to invent some extraneou=
s syntax or a new `expected` member function or whatever, to tell static an=
alysis tools, "Yes, I know that I'm reading from an untested expected. Shut=
up about it."<br><br>Or you can just have 2b and 2c users call the throwin=
g version of the function. Then it's clear to everyone what the deal is.<br=
><br>My point is that `value` throwing is the right move, but nobody should=
be catching what `value` throws. So what it throws is irrelevant, save for=
the fact that it shouldn't be throwing something that could accidentally b=
e caught. So throwing a new type like `bad_expected_access` is the right mo=
ve. Putting the error code in there is a nice touch, but it ought to be mor=
e or less irrelevant to users.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_496_208485643.1433531940526--
------=_Part_495_1375362793.1433531940526--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Fri, 05 Jun 2015 22:53:11 +0200
Raw View
This is a multi-part message in MIME format.
--------------020707000507090809080600
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit :
> On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigante wrote:
>
> C++ is not a functional language, nor is it going to become one in the=20
> near future. What happens in "the strongly typed functional=20
> programming world" is all well and good... for that world. But that=20
> /alone/ doesn't make it good for C++ or any other world.
Why do you say that C++ is not a functional language? C++ is=20
multi-paradigm language, imperative, object oriented, functional, ...
>
> You need to justify this with something more than "this is how things=20
> work in functional programming monad pattern matching."
The question is, if expected can be seen as a monad, why don't profit=20
from all the experience other languages have had with this abstraction.=20
Just because C++ has already exceptions is not a good reason for me,=20
because the use cases expected try to cover in C++ is when the user=20
don't want exceptions.
>
> We don't have lambda expressions because they're useful "in functional=20
> programming"; we have them because it's useful to be able to, quickly=20
> and easily, pass stateful functions to various APIs in C++.
Labmda expressions are useful by them selves. You have the lambda=20
calculus. This is the base of the functional programming languages. C++=20
lambdas are based on this mathematical model that has been there for=20
decades. C++ Lambdas have just been adapted to the C++ world.
> Similarly, we shouldn't have `expected` because it's how error=20
> handling is done "in functional programming". We should have it=20
> because it offers up a very useful option for handling errors locally=20
> in C++, solving a number of problems associated with returning error=20
> codes.
Agreed.
>
> You should not try to turn `expected` into full-frontal "functional=20
> programming error handling." Ditch the "monads" and "pattern matching"=20
> and so forth; just focus on the basic proposal: a return type that is=20
> both error code and value.
Why?
When we consider sum types it is normal that we consider pattern=20
matching, them are undissociated. expected is a sum type. And also a=20
monad. And optional and future and a lot of classes are monads. So why=20
not make use the whole set of services that are associated.
>
> and that=E2=80=99s what
> expected would achieve (in contrast to C++03 exception
> specifications which were handled _at runtime_).
>
> The problem with Java checked exceptions is that the syntax simply
> is not up to the task.
> Every time you call a function, and you don=E2=80=99t want to propaga=
te
> the error to your caller,
> you have to add a try {}catch{} block. This disrupt the control
> flow: what if you need to do
> something different depending on the success of the call? instead
> of a simple branch you have
>
> to do one thing immediately after the call and another thing in a
> _whole other code block_.
> What if the recovery code is the same among a few calls? you can
> catch multiple exceptions
> of the same type in the same catch{} block, but then you cannot
> discriminate who raised the exception.
>
>
> Note that there are folks in this thread suggesting that something=20
> like this be (eventually) allowed:
>
> |
> expected.when{
> casegood (autovalue){usevalue;}
> casefailed (autoerror){handle error;}
> }
> |
>
> That looks an awful lot like a catch block. It seems to "disrupt the=20
> control flow" of the program.
This is just pattern matching. Even if there is not yet a concrete=20
proposal for pattern matching, I see it as unavoidable. Of course this=20
pattern matching would be adapted to the C++ world.
There are already a lot of libraries that have a match function. Having=20
it on the language makes the language more robust.
>
> It certainly pokes you in the eye a lot.
>
> It seems to me that not everyone agrees with you that one is=20
> particularly different from the other.
>
> Also, with regard to your question of "What if the recovery code is=20
> the same among a few calls?", `expected` doesn't exactly solve that=20
> one either.
I don't understand why?
> If you have two functions that return two `expected` objects, you=20
> still have to test each one in turn.
Note that pattern patching is not reserved to only one value. We have=20
also non-member functions like fmap that are adapted to this case.
>
> Also, if the recovery code "is the same among a few calls", you don't=20
> /need/ to discriminate between them. Not unless they're using=20
> different values that are specific to each call. And even that is=20
> solved by simply extracting the identical code into a function, that=20
> gets called with the parameters it needs.
>
> And again, `expected` doesn't solve that either. If the code uses=20
> different values that are specific to each error's cause, you still=20
> need to extract the code into functions and use parameters on them.
Having when() or pattern matching doesn't implies that you can not build=20
other abstraction on top of them. A concrete example would help to show =20
this can be done.
>
> Note that expected-style error handling also needs good syntax to
> be effectively used and not
> incur in the same problems: that=E2=80=99s why I advocate it for C++ =
only
> now that we=E2=80=99ll have the monadic
> 'do notation' provided by the await 2.0 proposal.
>
>
> What "await 2.0 proposal" are you referring to? What 'do notation'? I=20
> don't see anything like this in N4499.
>
> Also, something will seriously be wrong in C++ if this becomes=20
> legitimate error handling syntax:
>
> |
> autob =3D(await (await a).foo()).bar();
> |
>
> When I look at this, I see syntax that says "stop here until this=20
> completes", not syntax that says, "handle errors that are returned by=20
> this expression."
You should read again the resumable functions proposal. You are wrong.=20
The await operator has two roles; sequence the execution of the=20
continuation when the expression is ready and propagate the error if any=20
without executing the continuation. Usually for futures there is an=20
execution agent that would make the future ready. expected as optional=20
are always ready, so the continuation will be executed only if there is=20
no error. This is the magic.
Even if monadic interface are not as transparent as exception based=20
interface, they allow to make almost transparent the error propagation.
> Using the former for the /sole purpose/ of achieving the latter is a=20
> brutal language hack, not good syntax.
Any syntax can be abused and the distinction often this is a style=20
question, but you know that already.
>
> If you want to have syntax for dealing with `expected` more easily,=20
> then propose that.
There is no need to propose anything else if await proposal works. I=20
would prefer another name having less asynchronous connotation. but=20
awaiting something that is already ready just works. In the original=20
Expected proposal I used the 'expect' keyword, 'try' could work as well=20
as 'do'.
> But don't hijack a perfectly good coroutine proposal just to graft=20
> `expected`-based error handling onto it. Make it a separate construct,=20
> rather than some kind of Congressional rider amendment that's attached=20
> to a must-pass budget appropriations bill.
>
> That's just disingenuous.
There is no hijacking at all. The features is defined as it is, and it=20
allows this kind of usage. I could concede that the original proposed=20
feature was not intended to managed these cases, but when the feature=20
was generalized to other types other than future, what was proposed was=20
some kind of do-notation adapted to the C++ language. You can believe it=20
or not, this is a fact.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------020707000507090809080600
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 05/06/15 18:36, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola
Gigante wrote:<br>
<div><br>
C++ is not a functional language, nor is it going to become
one in the near future. What happens in "the strongly typed
functional programming world" is all well and good... for that
world. But that <i>alone</i> doesn't make it good for C++ or
any other world.<br>
</div>
</div>
</blockquote>
Why do you say that C++ is not a functional language? C++ is
multi-paradigm language, imperative, object oriented, functional,
...<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
You need to justify this with something more than "this is how
things work in functional programming monad pattern matching."<br=
>
</div>
</div>
</blockquote>
The question is, if expected can be seen as a monad, why don't
profit from all the experience other languages have had with this
abstraction. Just because C++ has already exceptions is not a good
reason for me, because the use cases expected try to cover in C++ is
when the user don't want exceptions.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
We don't have lambda expressions because they're useful "in
functional programming"; we have them because it's useful to
be able to, quickly and easily, pass stateful functions to
various APIs in C++. </div>
</div>
</blockquote>
Labmda expressions are useful by them selves. You have the lambda
calculus. This is the base of the functional programming languages.
C++ lambdas are based on this mathematical model that has been there
for decades. C++ Lambdas have just been adapted to the C++ world.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>Similarly, we shouldn't have `expected` because it's how
error handling is done "in functional programming". We should
have it because it offers up a very useful option for handling
errors locally in C++, solving a number of problems associated
with returning error codes.<br>
</div>
</div>
</blockquote>
Agreed.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
You should not try to turn `expected` into full-frontal
"functional programming error handling." Ditch the "monads"
and "pattern matching" and so forth; just focus on the basic
proposal: a return type that is both error code and value.<br>
</div>
</div>
</blockquote>
Why?<br>
When we consider sum types it is normal that we consider pattern
matching, them are undissociated. expected is a sum type. And also a
monad. And optional and future and a lot of classes are monads. So
why not make use the whole set of services that are associated.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>
<div> and that=E2=80=99s what</div>
<div>expected would achieve (in contrast to C++03
exception specifications which were handled _at
runtime_).</div>
<div><br>
</div>
<div>The problem with Java checked exceptions is that the
syntax simply is not up to the task.</div>
<div>Every time you call a function, and you don=E2=80=99t wa=
nt to
propagate the error to your caller,</div>
<div>you have to add a try {}catch{} block. This disrupt
the control flow: what if you need to do</div>
<div>something different depending on the success of the
call? instead of a simple branch you have</div>
</div>
</div>
</blockquote>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>
<div>to do one thing immediately after the call and
another thing in a _whole other code block_.</div>
<div>What if the recovery code is the same among a few
calls? you can catch multiple exceptions</div>
<div>of the same type in the same catch{} block, but then
you cannot discriminate who raised the exception.</div>
</div>
</div>
</blockquote>
<div><br>
Note that there are folks in this thread suggesting that
something like this be (eventually) allowed:<br>
<br>
<div class=3D"prettyprint" style=3D"background-color: rgb(250,
250, 250); border-color: rgb(187, 187, 187); border-style:
solid; border-width: 1px; word-wrap: break-word;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #000;"
class=3D"styled-by-prettify">=C2=A0 expected</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">.</sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">when<=
/span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">case</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> good
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">auto</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> valu=
e</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">use</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> valu=
e</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">case</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
failed </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">auto</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> erro=
r</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">
handle error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"> </span><span
style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">}</span></div>
</code></div>
<div><br>
</div>
That looks an awful lot like a catch block. It seems to
"disrupt the control flow" of the program.<br>
</div>
</div>
</blockquote>
This is just pattern matching. Even if there is not yet a concrete
proposal for pattern matching, I see it as unavoidable. Of course
this pattern matching would be adapted to the C++ world.<br>
There are already a lot of libraries that have a match function.
Having it on the language makes the language more robust.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
It certainly pokes you in the eye a lot.<br>
<br>
It seems to me that not everyone agrees with you that one is
particularly different from the other.<br>
<br>
Also, with regard to your question of "What if the recovery
code is the same among a few calls?", `expected` doesn't
exactly solve that one either. </div>
</div>
</blockquote>
I don't understand why?<br>
<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>If you have two functions that return two `expected`
objects, you still have to test each one in turn.<br>
</div>
</div>
</blockquote>
Note that pattern patching is not reserved to only one value. We
have also non-member functions like fmap that are adapted to this
case.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
Also, if the recovery code "is the same among a few calls",
you don't <i>need</i> to discriminate between them. Not
unless they're using different values that are specific to
each call. And even that is solved by simply extracting the
identical code into a function, that gets called with the
parameters it needs.<br>
<br>
And again, `expected` doesn't solve that either. If the code
uses different values that are specific to each error's cause,
you still need to extract the code into functions and use
parameters on them.<br>
</div>
</div>
</blockquote>
Having when() or pattern matching doesn't implies that you can not
build other abstraction on top of them. A concrete example would
help to show=C2=A0 this can be done.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>
<div>Note that expected-style error handling also needs
good syntax to be effectively used and not</div>
<div>incur in the same problems: that=E2=80=99s why I advocat=
e it
for C++ only now that we=E2=80=99ll have the monadic</div>
<div>'do notation' provided by the await 2.0 proposal.</div>
</div>
</div>
</blockquote>
<div><br>
What "await 2.0 proposal" are you referring to? What 'do
notation'? I don't see anything like this in N4499.<br>
<br>
Also, something will seriously be wrong in C++ if this becomes
legitimate error handling syntax:<br>
<br>
<div class=3D"prettyprint" style=3D"background-color: rgb(250,
250, 250); border-color: rgb(187, 187, 187); border-style:
solid; border-width: 1px; word-wrap: break-word;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #008;"
class=3D"styled-by-prettify">auto</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> b </=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">await
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify">await a</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">).</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">foo</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">()).<=
/span><span
style=3D"color: #000;" class=3D"styled-by-prettify">bar</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</=
span></div>
</code></div>
<br>
When I look at this, I see syntax that says "stop here until
this completes", not syntax that says, "handle errors that are
returned by this expression." </div>
</div>
</blockquote>
You should read again the resumable functions proposal. You are
wrong. The await operator has two roles; sequence the execution of
the continuation when the expression is ready and propagate the
error if any without executing the continuation. Usually for futures
there is an execution agent that would make the future ready.
expected as optional are always ready, so the continuation will be
executed only if there is no error. This is the magic.<br>
Even if monadic interface are not as transparent as exception based
interface, they allow to make almost transparent the error
propagation.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>Using the former for the <i>sole purpose</i> of achieving
the latter is a brutal language hack, not good syntax.<br>
</div>
</div>
</blockquote>
Any syntax can be abused and the distinction often this is a style
question, but you know that already.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
If you want to have syntax for dealing with `expected` more
easily, then propose that. </div>
</div>
</blockquote>
There is no need to propose anything else if await proposal works. I
would prefer another name having less asynchronous connotation. but
awaiting something that is already ready just works. In the original
Expected proposal I used the 'expect' keyword, 'try' could work as
well as 'do'.<br>
<blockquote
cite=3D"mid:86769ab5-9309-450e-ba03-fe849e377b67@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>But don't hijack a perfectly good coroutine proposal just
to graft `expected`-based error handling onto it. Make it a
separate construct, rather than some kind of Congressional
rider amendment that's attached to a must-pass budget
appropriations bill.<br>
<br>
That's just disingenuous.<br>
</div>
</div>
</blockquote>
There is no hijacking at all. The features is defined as it is, and
it allows this kind of usage. I could concede that the original
proposed feature was not intended to managed these cases, but when
the feature was generalized to other types other than future, what
was proposed was some kind of do-notation adapted to the C++
language. You can believe it or not, this is a fact.<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------020707000507090809080600--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Fri, 05 Jun 2015 23:34:39 +0200
Raw View
This is a multi-part message in MIME format.
--------------000609040504010105080507
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
> On Friday, June 5, 2015 at 2:47:11 PM UTC-4, Matthew Woehlke wrote:
>
> On 2015-06-05 14:13, Nicol Bolas wrote:
> > 4) `.value()` throws the `bad_expected_access<T>` template
> class. Which
> > means that's the type the user normally has to catch (when not
> using
> > `exception_ptr`). Which means that catching code needs to
> recognize that
> > the throwing code was using `expected` to do the throwing. Why
> should it?
>
> See, *this* is the point I was trying to make. *Why* does it do that?
> Should it not throw an exception indicative of *why* it doesn't
> have a
> value? (In particular, if the error is itself an exception,
> shouldn't it
> just throw that?)
>
> At least there should be a method that does that. Perhaps even
> something
> short, like operator*.
>
>
> It really comes down to how you expect to use, well, `expected`.
>
> `expected` is for local error handling. Higher level code shouldn't=20
> have to know about it; it should be an implementation detail to them.
Why do you want other use expected as you think it must be used?
>
> But `value` throws an exception, and this is the right call. When a=20
> user calls `value`, one of two things is true:
>
> 1) The user has previously verified that this `expected` instance=20
> contains a value. And thus it will never throw.
>
> 2) The user has not verified that the `expected` instance contains a=20
> value. And thus it may throw.
>
> #2 would happen in two circumstances:
>
> 2a) a programming bug
Why. expected is always ready. Either it contains a value or the reason=20
why it doesn't contain it. I don't see where is the bug.
>
> 2b) deliberate design
>
> 2c) the user wants to catch the exception thrown. This is what you're=20
> arguing for
>
> With 2a, the program ought to terminate, since continuing forward in=20
> the event of an obvious programming bug is usually not a good idea.
>
> With 2b, the user has effectively /decided/ that termination is a=20
> legitimate response to this error.
If the user is the one that has written the call to=20
expected<T>::value(), what the user wants is the value and is=20
considering that if the value is not there this is an exceptional case.=20
If this user consider that it is not exceptional it should check it before.
>
> OK, so... what about static analysis tools? We already have great=20
> static tools that can detect the use of many uninitialized values.
expected as optional, and I hope would variant, are never uninitialized=20
as these classes have default constructor.
> So it's reasonable to assume that such tools will be expanded in the=20
> face of `optional` and `expected`, detecting when you use them without=20
> explicitly checking that they are real values.
I have the impression that you don't understand all these proposals or=20
maybe I don't understand what you mean.
>
> The purpose of this is to track down bugs caused by 2a. However, 2a is=20
> indistinguishable from 2b and 2c. So static analysis tools will=20
> complain about those cases. So now you'll have to invent some=20
> extraneous syntax or a new `expected` member function or whatever, to=20
> tell static analysis tools, "Yes, I know that I'm reading from an=20
> untested expected. Shut up about it."
>
> Or you can just have 2b and 2c users call the throwing version of the=20
> function. Then it's clear to everyone what the deal is.
>
IMO, the premises are wrong, and so, the conclusion has no importance.
> My point is that `value` throwing is the right move, but nobody should=20
> be catching what `value` throws.
Why?
> So what it throws is irrelevant, save for the fact that it shouldn't=20
> be throwing something that could accidentally be caught. So throwing a=20
> new type like `bad_expected_access` is the right move.
I have the impression also that you don't want to admit that expected=20
can be use to store whatever the user wants to report as error.
> Putting the error code in there is a nice touch, but it ought to be=20
> more or less irrelevant to users.
>
You can consider it as irrelevant for I don't know which reason, other=20
could find all this information quite relevant. All this is not=20
important, a generic tools has multiple usages. In the extreme you have=20
expected<T, null_t>, that would not cover any error information and that=20
is isomorphic to optional<T> but used in a different context.
Best regards,
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------000609040504010105080507
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 05/06/15 21:19, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 2:47:11 PM UTC-4,
Matthew Woehlke wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On
2015-06-05 14:13, Nicol Bolas wrote:
<br>
> 4) `.value()` throws the `bad_expected_access<T>`
template class. Which <br>
> means that's the type the user normally has to catch
(when not using <br>
> `exception_ptr`). Which means that catching code needs to
recognize that <br>
> the throwing code was using `expected` to do the
throwing. Why should it?
<br>
<br>
See, *this* is the point I was trying to make. *Why* does it
do that?
<br>
Should it not throw an exception indicative of *why* it
doesn't have a
<br>
value? (In particular, if the error is itself an exception,
shouldn't it
<br>
just throw that?)
<br>
<br>
At least there should be a method that does that. Perhaps even
something
<br>
short, like operator*.
<br>
</blockquote>
<div><br>
It really comes down to how you expect to use, well,
`expected`.<br>
<br>
`expected` is for local error handling. Higher level code
shouldn't have to know about it; it should be an
implementation detail to them.<br>
</div>
</div>
</blockquote>
Why do you want other use expected as you think it must be used?=C2=A0 =
<br>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
But `value` throws an exception, and this is the right call.
When a user calls `value`, one of two things is true:<br>
<br>
1) The user has previously verified that this `expected`
instance contains a value. And thus it will never throw.<br>
<br>
2) The user has not verified that the `expected` instance
contains a value. And thus it may throw.<br>
<br>
#2 would happen in two circumstances:<br>
<br>
2a) a programming bug <br>
</div>
</div>
</blockquote>
Why. expected is always ready. Either it contains a value or the
reason why it doesn't contain it. I don't see where is the bug.<br>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
2b) deliberate design<br>
<br>
2c) the user wants to catch the exception thrown. This is what
you're arguing for<br>
<br>
With 2a, the program ought to terminate, since continuing
forward in the event of an obvious programming bug is usually
not a good idea.<br>
<br>
With 2b, the user has effectively <i>decided</i> that
termination is a legitimate response to this error.<br>
</div>
</div>
</blockquote>
If the user is the one that has written the call to
expected<T>::value(), what the user wants is the value and is
considering that if the value is not there this is an exceptional
case. If this user consider that it is not exceptional it should
check it before.<br>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
OK, so... what about static analysis tools? We already have
great static tools that can detect the use of many
uninitialized values. </div>
</div>
</blockquote>
expected as optional, and I hope would variant, are never
uninitialized as these classes have default constructor.<br>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>So it's reasonable to assume that such tools will be
expanded in the face of `optional` and `expected`, detecting
when you use them without explicitly checking that they are
real values.<br>
</div>
</div>
</blockquote>
I have the impression that you don't understand all these proposals
or maybe I don't understand what you mean.<br>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
The purpose of this is to track down bugs caused by 2a.
However, 2a is indistinguishable from 2b and 2c. So static
analysis tools will complain about those cases. So now you'll
have to invent some extraneous syntax or a new `expected`
member function or whatever, to tell static analysis tools,
"Yes, I know that I'm reading from an untested expected. Shut
up about it."<br>
<br>
Or you can just have 2b and 2c users call the throwing version
of the function. Then it's clear to everyone what the deal is.<br=
>
<br>
</div>
</div>
</blockquote>
IMO, the premises are wrong, and so, the conclusion has no
importance.<br>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>My point is that `value` throwing is the right move, but
nobody should be catching what `value` throws. </div>
</div>
</blockquote>
Why?<br>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>So what it throws is irrelevant, save for the fact that it
shouldn't be throwing something that could accidentally be
caught. So throwing a new type like `bad_expected_access` is
the right move. </div>
</div>
</blockquote>
I have the impression also that you don't want to admit that
expected can be use to store whatever the user wants to report as
error.<br>
<blockquote
cite=3D"mid:d1a1020f-4c67-4b24-9e7e-8c2cb1f4b0da@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>Putting the error code in there is a nice touch, but it
ought to be more or less irrelevant to users.<br>
</div>
</div>
<br>
</blockquote>
You can consider it as irrelevant for I don't know which reason,
other could find all this information quite relevant. All this is
not important, a generic tools has multiple usages. In the extreme
you have expected<T, null_t>, that would not cover any error
information and that is isomorphic to optional<T> but used in
a different context.<br>
<br>
Best regards,<br>
Vicente<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------000609040504010105080507--
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Fri, 05 Jun 2015 18:41:33 -0400
Raw View
On 2015-06-05 17:34, Vicente J. Botet Escriba wrote:
> Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
>> OK, so... what about static analysis tools? We already have great
>> static tools that can detect the use of many uninitialized values.
>
> expected as optional, and I hope would variant, are never uninitialized
> as these classes have default constructor.
Not the expected/optional itself, but the contained value.
IOW, this is a (potential) error:
auto x =3D function_that_returns_expected_or_optional;
do_something(x.value());
....because you didn't check that 'x' actually *has* a value, and thus
value() might throw.
Nicol is of the opinion that one should never write code like this, even
if throwing from the context where value() is called if there is no
value is the intended behavior.
I have to ask, though: in that case, why throw at all?
Really, I envision expected as a 'delayed throw' mechanism. The point is
to return an expected instead of throwing immediately, and instead delay
*the throw that otherwise would have happened* until the user calls
value(), thus giving a window where the user can choose to handle the
error before an exception is thrown.
If you're *not* going to implement it that way, then why even throw an
exception? Why not just terminate the program? Or make it UB? IMO it's
*much* more useful for expected to be an exception delaying mechanism
than to do something that (by Nicol's assertion) is useless and
can/should only ever result in program termination.
--=20
Matthew
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 5 Jun 2015 22:40:41 -0700 (PDT)
Raw View
------=_Part_257_1969512931.1433569241604
Content-Type: multipart/alternative;
boundary="----=_Part_258_290896459.1433569241604"
------=_Part_258_290896459.1433569241604
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Botet Escriba wrote=
:
>
> Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit :
> =20
> On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigante wrote:
>
> C++ is not a functional language, nor is it going to become one in the=20
> near future. What happens in "the strongly typed functional programming=
=20
> world" is all well and good... for that world. But that *alone* doesn't=
=20
> make it good for C++ or any other world.
> =20
> Why do you say that C++ is not a functional language? C++ is=20
> multi-paradigm language, imperative, object oriented, functional, ...
>
To call something a "functional programming language" requires the=20
inability to break the functional paradigm (admittedly, for varying degrees=
=20
of the word "break"). C++ allows you to restrict yourself, to willingly=20
limit yourself to the functional programming box. What people think of when=
=20
they say "functional programming language" doesn't give you the choice; you=
=20
live within the box or write in some other language.
That's why C++ is not a functional language. It permits functional=20
programming, but it doesn't *require* it.
> You need to justify this with something more than "this is how things=
=20
> work in functional programming monad pattern matching."
> =20
> The question is, if expected can be seen as a monad, why don't profit fro=
m=20
> all the experience other languages have had with this abstraction.
>
C++ would only be considered to "profit" from this if you see the addition=
=20
of functional elements to the language as a priori good. I do not see the=
=20
profit in grafting functional elements into C++.
> We don't have lambda expressions because they're useful "in functional=
=20
> programming"; we have them because it's useful to be able to, quickly and=
=20
> easily, pass stateful functions to various APIs in C++.=20
> =20
> Labmda expressions are useful by them selves. You have the lambda=20
> calculus. This is the base of the functional programming languages.
>
Yes, they are. But as I said, C++ doesn't have them *for that reason*. C++=
=20
did not add lambda functions to be the basis of a functional programming=20
model. It added them because they were useful to *many uses* of C++,=20
functional or not.
So you have to provide a reason to do something beyond "that's how=20
functional programming does it" or "functional languages have something a=
=20
lot like that".
> You should not try to turn `expected` into full-frontal "functional=20
> programming error handling." Ditch the "monads" and "pattern matching" an=
d=20
> so forth; just focus on the basic proposal: a return type that is both=20
> error code and value.
> =20
> Why?
> When we consider sum types it is normal that we consider pattern matching=
,=20
> them are undissociated. expected is a sum type. And also a monad. And=20
> optional and future and a lot of classes are monads. So why not make use=
=20
> the whole set of services that are associated.
>
.... Because C++ is not a functional programming language. It has no "sum=20
types". It has no "monads". It has no "pattern matching". And it doesn't=20
need any of those.
Just because C++ has classes that look like certain functional concepts=20
doesn't mean that C++ ought to treat them the way functional languages=20
treat them. Like I said before, if you want to argue for these things, you=
=20
need to do so on C++'s terms, not on the terms of a functional language.=20
There must be some benefit to C++ besides, "that's how functional languages=
=20
deal with these."
> =20
> and that=E2=80=99s what
>> expected would achieve (in contrast to C++03 exception specifications=20
>> which were handled _at runtime_).
>>
>> The problem with Java checked exceptions is that the syntax simply is=
=20
>> not up to the task.
>> Every time you call a function, and you don=E2=80=99t want to propagate =
the error=20
>> to your caller,
>> you have to add a try {}catch{} block. This disrupt the control flow:=20
>> what if you need to do
>> something different depending on the success of the call? instead of a=
=20
>> simple branch you have
>> =20
> to do one thing immediately after the call and another thing in a=20
>> _whole other code block_.
>> What if the recovery code is the same among a few calls? you can catch=
=20
>> multiple exceptions
>> of the same type in the same catch{} block, but then you cannot=20
>> discriminate who raised the exception.
>> =20
>
> Note that there are folks in this thread suggesting that something like=
=20
> this be (eventually) allowed:
>
> expected.when {
> case good (auto value) { use value; }
> case failed (auto error) { handle error; }
> }
> =20
> That looks an awful lot like a catch block. It seems to "disrupt the=20
> control flow" of the program.
> =20
> This is just pattern matching. Even if there is not yet a concrete=20
> proposal for pattern matching, I see it as unavoidable. Of course this=20
> pattern matching would be adapted to the C++ world.
> There are already a lot of libraries that have a match function. Having i=
t=20
> on the language makes the language more robust.
>
This "makes the language more robust" only to those who consider the=20
functional programming model to be the one true way of achieving robust=20
code.
> It certainly pokes you in the eye a lot.
>
> It seems to me that not everyone agrees with you that one is particularly=
=20
> different from the other.
>
> Also, with regard to your question of "What if the recovery code is the=
=20
> same among a few calls?", `expected` doesn't exactly solve that one eithe=
r.=20
> =20
> I don't understand why?
>
Well, those calls would look something like this:
expected<T, error_code> v1 =3D stuff();
v1.when{
case good (auto value) { use v1; }
case failed (auto error) { handle error; }
}
//other processing
expected<T, error_code> v2 =3D stuff2();
v2.when{
case good (auto value) { use v2; }
case failed (auto error) { handle error; }
}
See how both of them use the same "handle error" code? That's what he was=
=20
talking about when he said "What if the recovery code is the same among a=
=20
few calls?" `expected`, even using this `when` syntax, doesn't improve=20
things compared to the exception case:
try{
T v1 =3D stuff();
use v1;
}
catch(error){ handle error;}
//other processing
try{
T v2 =3D stuff2();
use v2;
}
catch(error){ handle error;}
Indeed, some might even argue that the exception case is easier to read,=20
since there's no extraneous syntax between the initialization of the `T`=20
values and their use.
> Note that expected-style error handling also needs good syntax to be=
=20
>> effectively used and not
>> incur in the same problems: that=E2=80=99s why I advocate it for C++ onl=
y now=20
>> that we=E2=80=99ll have the monadic
>> 'do notation' provided by the await 2.0 proposal.
>> =20
>
> What "await 2.0 proposal" are you referring to? What 'do notation'? I=20
> don't see anything like this in N4499.
>
> Also, something will seriously be wrong in C++ if this becomes legitimate=
=20
> error handling syntax:
>
> auto b =3D (await (await a).foo()).bar();
> =20
> When I look at this, I see syntax that says "stop here until this=20
> completes", not syntax that says, "handle errors that are returned by thi=
s=20
> expression."=20
> =20
> You should read again the resumable functions proposal.
>
*Which* "resumable functions proposal"? The most recent thing on this=20
subject that I can find (N4499) is pure standardese; trying to figure out=
=20
what the dozens of changes across dozens of chapters actually means is=20
painful. Even finding out something as simple as what `await` means when=20
applied to an expression is byzantine.
If you're talking about N4402, well, that was harder to find, since it's=20
not in the repository=20
<http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/>. I managed to=20
find it on isocpp.org <https://isocpp.org/blog/2015/04/n4402>. I haven't=20
gone through it in any detail, but I haven't seen the part that said=20
`await` means error handling for `expected`.
Equally importantly, what I was referring to was the use of the `await`=20
keyword. Which is intended, by both N4402 and N4499, to be used for some=20
form of delaying of processing, so that a task can be resolved. Hence my=20
use of the phrase, "when I *look* at this..."
If you have to tell people, "`await` doesn't mean waiting on something to=
=20
be finished <http://dictionary.reference.com/browse/await?db=3D*>," that's=
=20
suggests pretty strongly that you're using the wrong tool to get a job done=
..
> But don't hijack a perfectly good coroutine proposal just to graft=20
> `expected`-based error handling onto it. Make it a separate construct,=20
> rather than some kind of Congressional rider amendment that's attached to=
a=20
> must-pass budget appropriations bill.
>
> That's just disingenuous.
> =20
> There is no hijacking at all. The features is defined as it is, and it=20
> allows this kind of usage. I could concede that the original proposed=20
> feature was not intended to managed these cases,
>
That's an admission of hijacking. If something is intended to do X, and=20
then you make it do Y, where Y is decidedly unlike X in more or less every=
=20
way, you have *hijacked* that something, turning it into a backdoor to get=
=20
Y accomplished. You even admitted this when you said, "I would prefer=20
another name having less asynchronous connotation." If you'd prefer a=20
different name, then clearly that something isn't meant to perform that=20
function.
It's things like this that got us our current template metaprogramming=20
functionality. And while there have been good things that came of it, it=20
requires such a degree of expert knowledge that only a minority of C++=20
programmers can use it. Whereas, if it were a designed feature rather than=
=20
an ad-hoc hack, it would have been designed to be more useable.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_258_290896459.1433569241604
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Bo=
tet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 18:36, Nicol Bolas a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola
Gigante wrote:<br>
<div><br>
C++ is not a functional language, nor is it going to become
one in the near future. What happens in "the strongly typed
functional programming world" is all well and good... for that
world. But that <i>alone</i> doesn't make it good for C++ or
any other world.<br>
</div>
</div>
</blockquote>
Why do you say that C++ is not a functional language? C++ is
multi-paradigm language, imperative, object oriented, functional,
...<br></div></blockquote><div><br>To call something a "functional prog=
ramming language" requires the inability to break the functional paradigm (=
admittedly, for varying degrees of the word "break"). C++ allows you to res=
trict yourself, to willingly limit yourself to the functional programming b=
ox. What people think of when they say "functional programming language" do=
esn't give you the choice; you live within the box or write in some other l=
anguage.<br><br>That's why C++ is not a functional language. It permits fun=
ctional programming, but it doesn't <i>require</i> it.<br></div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000"=
>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
You need to justify this with something more than "this is how
things work in functional programming monad pattern matching."<br=
>
</div>
</div>
</blockquote>
The question is, if expected can be seen as a monad, why don't
profit from all the experience other languages have had with this
abstraction.</div></blockquote><div><br>C++ would only be considered to=
"profit" from this if you see the addition of functional elements to the l=
anguage as a priori good. I do not see the profit in grafting functional el=
ements into C++.<br></div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
We don't have lambda expressions because they're useful "in
functional programming"; we have them because it's useful to
be able to, quickly and easily, pass stateful functions to
various APIs in C++. </div>
</div>
</blockquote>
Labmda expressions are useful by them selves. You have the lambda
calculus. This is the base of the functional programming languages.</di=
v></blockquote><div><br>Yes, they are. But as I said, C++ doesn't have them=
<i>for that reason</i>. C++ did not add lambda functions to be the basis o=
f a functional programming model. It added them because they were useful to=
<i>many uses</i> of C++, functional or not.<br><br>So you have to provide =
a reason to do something beyond "that's how functional programming does it"=
or "functional languages have something a lot like that".</div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000"=
>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
You should not try to turn `expected` into full-frontal
"functional programming error handling." Ditch the "monads"
and "pattern matching" and so forth; just focus on the basic
proposal: a return type that is both error code and value.<br>
</div>
</div>
</blockquote>
Why?<br>
When we consider sum types it is normal that we consider pattern
matching, them are undissociated. expected is a sum type. And also a
monad. And optional and future and a lot of classes are monads. So
why not make use the whole set of services that are associated.<br></di=
v></blockquote><div><br>... Because C++ is not a functional programming lan=
guage. It has no "sum types". It has no "monads". It has no "pattern matchi=
ng". And it doesn't need any of those.<br><br>Just because C++ has classes =
that look like certain functional concepts doesn't mean that C++ ought to t=
reat them the way functional languages treat them. Like I said before, if y=
ou want to argue for these things, you need to do so on C++'s terms, not on=
the terms of a functional language. There must be some benefit to C++ besi=
des, "that's how functional languages deal with these."<br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000=
">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div style=3D"word-wrap:break-word">
<div>
<div> and that=E2=80=99s what</div>
<div>expected would achieve (in contrast to C++03
exception specifications which were handled _at
runtime_).</div>
<div><br>
</div>
<div>The problem with Java checked exceptions is that the
syntax simply is not up to the task.</div>
<div>Every time you call a function, and you don=E2=80=99t wa=
nt to
propagate the error to your caller,</div>
<div>you have to add a try {}catch{} block. This disrupt
the control flow: what if you need to do</div>
<div>something different depending on the success of the
call? instead of a simple branch you have</div>
</div>
</div>
</blockquote>
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div style=3D"word-wrap:break-word">
<div>
<div>to do one thing immediately after the call and
another thing in a _whole other code block_.</div>
<div>What if the recovery code is the same among a few
calls? you can catch multiple exceptions</div>
<div>of the same type in the same catch{} block, but then
you cannot discriminate who raised the exception.</div>
</div>
</div>
</blockquote>
<div><br>
Note that there are folks in this thread suggesting that
something like this be (eventually) allowed:<br>
<br>
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><cod=
e>
<div><span style=3D"color:#000"> expected</span><span s=
tyle=3D"color:#660">.</span><span style=3D"color:#008">when</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D=
"color:#000"><br>
</span><span style=3D"color:#008">case</spa=
n><span style=3D"color:#000"> good
</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#008">auto</span><span style=3D"color:#000"> value</span><span style=3D=
"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#00=
8">use</span><span style=3D"color:#000"> value</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
}</span><span style=3D"color:#000"><br>
</span><span style=3D"color:#008">case</spa=
n><span style=3D"color:#000">
failed </span><span style=3D"color:#660">(</span><span st=
yle=3D"color:#008">auto</span><span style=3D"color:#000"> error</span><span=
style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">{</span><span style=3D"color:#000">
handle error</span><span style=3D"color:#660">;</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">}</span><span st=
yle=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span></div>
</code></div>
<div><br>
</div>
That looks an awful lot like a catch block. It seems to
"disrupt the control flow" of the program.<br>
</div>
</div>
</blockquote>
This is just pattern matching. Even if there is not yet a concrete
proposal for pattern matching, I see it as unavoidable. Of course
this pattern matching would be adapted to the C++ world.<br>
There are already a lot of libraries that have a match function.
Having it on the language makes the language more robust.<br></div></bl=
ockquote><div><br>This "makes the language more robust" only to those who c=
onsider the functional programming model to be the one true way of achievin=
g robust code.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div b=
gcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
It certainly pokes you in the eye a lot.<br>
<br>
It seems to me that not everyone agrees with you that one is
particularly different from the other.<br>
<br>
Also, with regard to your question of "What if the recovery
code is the same among a few calls?", `expected` doesn't
exactly solve that one either. </div>
</div>
</blockquote>
I don't understand why?<br></div></blockquote><div><br>Well, those call=
s would look something like this:<br><br><div class=3D"prettyprint" style=
=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187);=
border-style: solid; border-width: 1px; word-wrap: break-word;"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;=
" class=3D"styled-by-prettify">expected</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> error_code</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">></span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> v1 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> stuff</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>v1</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">when</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">case</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> good </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> value</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">use</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> v1</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">case</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> failed </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> error</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> handle error</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br><br></span><span style=3D"color: #800;" class=3D"styled-by-prettify">//=
other processing</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br><br>expected</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> error_code<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">></span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> v2 </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> stuff2</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"><br>v2</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">.</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">when</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">case</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> good </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">au=
to</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> value</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">use</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> v2</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">ca=
se</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> failed =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> error</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> handle error</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
</div></code></div><br>See how both of them use the same "handle error" cod=
e? That's what he was talking about when he said "What if the recovery
code is the same among a few calls?" `expected`, even using this =
`when` syntax, doesn't improve things compared to the exception case:<br><b=
r><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250);=
border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; =
word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #008;" class=3D"styled-by-prettify">try</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>T v1 </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> stuff</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">use</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> v1</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">catch</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">error</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">){</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> handle error</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">;}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br></span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">//other processing</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">try</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>T v2 </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> stuff2</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span><span style=3D"color: #008;" class=3D"styled-by-prettify">use</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> v2</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">catch</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">error</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">){</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ha=
ndle error</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
;}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an></div></code></div><br>Indeed, some might even argue that the exception =
case is easier to read, since there's no extraneous syntax between the init=
ialization of the `T` values and their use.<br></div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
=20
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div style=3D"word-wrap:break-word">
<div>
<div>Note that expected-style error handling also needs
good syntax to be effectively used and not</div>
<div>incur in the same problems: that=E2=80=99s why I advocat=
e it
for C++ only now that we=E2=80=99ll have the monadic</div>
<div>'do notation' provided by the await 2.0 proposal.</div>
</div>
</div>
</blockquote>
<div><br>
What "await 2.0 proposal" are you referring to? What 'do
notation'? I don't see anything like this in N4499.<br>
<br>
Also, something will seriously be wrong in C++ if this becomes
legitimate error handling syntax:<br>
<br>
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><cod=
e>
<div><span style=3D"color:#008">auto</span><span style=3D"col=
or:#000"> b </span><span style=3D"color:#660">=3D</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">(</span><span style=3D"color:#00=
0">await
</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#000">await a</span><span style=3D"color:#660">).</span><span style=3D"=
color:#000">foo</span><span style=3D"color:#660">()).</span><span style=3D"=
color:#000">bar</span><span style=3D"color:#660">();</span></div>
</code></div>
<br>
When I look at this, I see syntax that says "stop here until
this completes", not syntax that says, "handle errors that are
returned by this expression." </div>
</div>
</blockquote>
You should read again the resumable functions proposal.</div></blockquo=
te><div><br><i>Which</i> "resumable functions proposal"? The most recent th=
ing on this subject that I can find (N4499) is pure standardese; trying to =
figure out what the dozens of changes across dozens of chapters actually me=
ans is painful. Even finding out something as simple as what `await` means =
when applied to an expression is byzantine.<br><br>If you're talking about =
N4402, well, that was harder to find, since it's not in <a href=3D"http://w=
ww.open-std.org/JTC1/SC22/WG21/docs/papers/2015/">the repository</a>. I man=
aged to find it<a href=3D"https://isocpp.org/blog/2015/04/n4402"> on isocpp=
..org</a>. I haven't gone through it in any detail, but I haven't seen the p=
art that said `await` means error handling for `expected`.<br><br>Equally i=
mportantly, what I was referring to was the use of the `await` keyword. Whi=
ch is intended, by both N4402 and N4499, to be used for some form of delayi=
ng of processing, so that a task can be resolved. Hence my use of the phras=
e, "when I <i>look</i> at this..."<br><br>If you have to tell people, "`awa=
it` doesn't mean <a href=3D"http://dictionary.reference.com/browse/await?db=
=3D*">waiting on something to be finished</a>," that's suggests pretty stro=
ngly that you're using the wrong tool to get a job done.<br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#00000=
0">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>But don't hijack a perfectly good coroutine proposal just
to graft `expected`-based error handling onto it. Make it a
separate construct, rather than some kind of Congressional
rider amendment that's attached to a must-pass budget
appropriations bill.<br>
<br>
That's just disingenuous.<br>
</div>
</div>
</blockquote>
There is no hijacking at all. The features is defined as it is, and
it allows this kind of usage. I could concede that the original
proposed feature was not intended to managed these cases,</div></blockq=
uote><div><br>That's an admission of hijacking. If something is intended to=
do X, and then you make it do Y, where Y is decidedly unlike X in more or =
less every way, you have <i>hijacked</i> that something, turning it into a =
backdoor to get Y accomplished. You even admitted this when you said, "I
would prefer another name having less asynchronous connotation." If you=
'd prefer a different name, then clearly that something isn't meant to perf=
orm that function.<br><br>It's things like this that got us our current tem=
plate metaprogramming functionality. And while there have been good things =
that came of it, it requires such a degree of expert knowledge that only a =
minority of C++ programmers can use it. Whereas, if it were a designed feat=
ure rather than an ad-hoc hack, it would have been designed to be more usea=
ble.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_258_290896459.1433569241604--
------=_Part_257_1969512931.1433569241604--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 5 Jun 2015 23:33:15 -0700 (PDT)
Raw View
------=_Part_259_2045791777.1433572395194
Content-Type: multipart/alternative;
boundary="----=_Part_260_261723922.1433572395194"
------=_Part_260_261723922.1433572395194
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, June 5, 2015 at 5:34:41 PM UTC-4, Vicente J. Botet Escriba wrote=
:
>
> Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
> =20
> On Friday, June 5, 2015 at 2:47:11 PM UTC-4, Matthew Woehlke wrote:=20
>>
>> On 2015-06-05 14:13, Nicol Bolas wrote:=20
>> > 4) `.value()` throws the `bad_expected_access<T>` template class. Whic=
h=20
>> > means that's the type the user normally has to catch (when not using=
=20
>> > `exception_ptr`). Which means that catching code needs to recognize=20
>> that=20
>> > the throwing code was using `expected` to do the throwing. Why should=
=20
>> it?=20
>>
>> See, *this* is the point I was trying to make. *Why* does it do that?=20
>> Should it not throw an exception indicative of *why* it doesn't have a=
=20
>> value? (In particular, if the error is itself an exception, shouldn't it=
=20
>> just throw that?)=20
>>
>> At least there should be a method that does that. Perhaps even something=
=20
>> short, like operator*.=20
>>
>
> It really comes down to how you expect to use, well, `expected`.
>
> `expected` is for local error handling. Higher level code shouldn't have=
=20
> to know about it; it should be an implementation detail to them.
> =20
> Why do you want other use expected as you think it must be used?
>
Because I may have to read, understand, and debug their code someday. And=
=20
seeing 5 layers of code pointlessly checking and returning `expected`=20
objects, just to get it to the place where they can be dealt with is not=20
helpful in that process.
And that assumes that such propagation is as simple as just returning that=
=20
object. For example, consider an integer parsing function that returns an=
=20
`expected<int, ec>`. Well, if the function that called it needs to=20
propagate that error... what does it return?
Maybe the function doing that particular integer parsing returns an=20
`array<int, 3>`, because it parses an array of integers in sequence. So you=
=20
can't just return the `expected` value itself; you now have to return a new=
=20
expected value: `expected<array<int, 3>, ec>`, which itself requires=20
copying the error object.
And maybe the next layer returns some other data structure, which itself=20
contains `array<int, 3>`s. So it has to return `expected<DataStructure,=20
ec>`. And so on up half-a-dozen layers until finally you get to the code=20
that can actually halt the processing and deliver an error. And God forbid=
=20
that one of those layers happen to be a `void` function, for which=20
`expected` isn't reasonable to use.
Or you just *throw an exception* like a sane person.
The syntactic burden of propagating `expected` failures through code is=20
non-trivial. The syntactic burden of propagating exceptions is (virtually)=
=20
*nil*. By contrast, the syntactic burden of `expected` in a local handler=
=20
is close to optimal. While the syntactic burden of exceptions in a local=20
context is substantial.
These are two tools, and when to use which is pretty obvious to most users.=
=20
So APIs should let users pick which one works best for their needs, rather=
=20
than trying to force one or the other.
> =20
> But `value` throws an exception, and this is the right call. When a user=
=20
> calls `value`, one of two things is true:
>
> 1) The user has previously verified that this `expected` instance contain=
s=20
> a value. And thus it will never throw.
>
> 2) The user has not verified that the `expected` instance contains a=20
> value. And thus it may throw.
>
> #2 would happen in two circumstances:
>
> 2a) a programming bug=20
> =20
> Why. expected is always ready. Either it contains a value or the reason=
=20
> why it doesn't contain it. I don't see where is the bug.
>
So you're saying that this:
expected<T, ec> t =3D foo_exp();
t.value().stuff();
is always 100% reasonable and correct code that does exactly what the user=
=20
intended it to do?=20
Nonsense.
The user may simply have forgotten to put `if(t)` in front of that=20
statement. *That* is the bug that 2a represents: the user *intended *to=20
check the value (wanted to be case #1) but simply forgot (accidentally=20
writing case 2). That is 2a.
> =20
> 2b) deliberate design
>
> 2c) the user wants to catch the exception thrown. This is what you're=20
> arguing for
>
> With 2a, the program ought to terminate, since continuing forward in the=
=20
> event of an obvious programming bug is usually not a good idea.
>
> With 2b, the user has effectively *decided* that termination is a=20
> legitimate response to this error.
> =20
> If the user is the one that has written the call to expected<T>::value(),=
=20
> what the user wants is the value and is considering that if the value is=
=20
> not there this is an exceptional case. If this user consider that it is n=
ot=20
> exceptional it should check it before.
>
I fail to see how your statement is in any way a response to what I said.=
=20
The user deliberately causes an exception to be thrown. They either intend=
=20
for that exception to be caught or they throw it knowing that it won't be.=
=20
2b is the case where they don't catch it.
> OK, so... what about static analysis tools? We already have great=20
> static tools that can detect the use of many uninitialized values.=20
> =20
> expected as optional, and I hope would variant, are never uninitialized a=
s=20
> these classes have default constructor.
>
The bit about uninitialized values was just to explain one of the uses of=
=20
static analysis tools to find bugs. I wasn't suggesting that these objects=
=20
would be uninitialized.
> So it's reasonable to assume that such tools will be expanded in the=20
> face of `optional` and `expected`, detecting when you use them without=20
> explicitly checking that they are real values.
> =20
> I have the impression that you don't understand all these proposals or=20
> maybe I don't understand what you mean.
>
.... all which proposals? There's only one (current) `expected` proposal.=20
That's the one we're talking about: N4109.
What I mean is very simple. This (case #1):
expected<T, ec> t =3D foo_exp();
if(t)
t.value().stuff();
is functional code. It cannot throw and it is correct, no matter what=20
foo_exp returns.
By contrast, this (case #2):
expected<T, ec> t =3D foo_exp();
t.value().stuff();
is potentially dangerous code. *Maybe* the user meant to throw an exception=
=20
(cases 2b and 2c). Or maybe he just forgot to check the value.
A static analysis tool can detect that a returned `expected` object is=20
being used without being checked. They can do quite a lot of such checking,=
=20
flowing from function to function to verify when something gets checked.=20
Having such static analysis is a *good thing*; it catches accidental bugs=
=20
caused by forgetting to check `expected` values.
However, any tool is only as good as its accuracy. Tools that miss errors=
=20
are not reliable; those that return lots of false positives will eventually=
=20
be ignored. Therefore, users should endeavor to avoid writing case #2 at=20
all. But there are legitimate reasons to write case #2: when you want=20
exceptions thrown.
Therefore, to make static analysis of `expected` use as useful as possible,=
=20
people who want exceptions thrown should... call functions that *throw=20
exceptions*:
T t =3D foo();
t.stuff();
`foo` here throws exceptions. That handles the case of 2b (where the user=
=20
just wants the app to die on an error) and 2c (where the user wants to=20
catch and process the error).
Because people should only be writing case 2 by accident, `.value` should=
=20
(in a working application) never throw. And there's no point in catching an=
=20
exception if it is never thrown.
And therefore:
> So what it throws is irrelevant, save for the fact that it shouldn't be=
=20
> throwing something that could accidentally be caught. So throwing a new=
=20
> type like `bad_expected_access` is the right move.=20
> =20
> I have the impression also that you don't want to admit that expected can=
=20
> be use to store whatever the user wants to report as error.
>
The user (by which I mean the code calling the function that returned the=
=20
error condition) *cannot* make that `expected` object store some data that=
=20
it isn't already able to store. It can create a *new* `expected` object=20
which stores a different error object. But it can't take an already=20
existing one and shove data into it that it's error code type is not able=
=20
to store.
Also, I'm not sure what the information that can be stored in an `expected`=
=20
object has to do with anything that I was talking about.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_260_261723922.1433572395194
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 5, 2015 at 5:34:41 PM UTC-4, Vicente J. Bo=
tet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 21:19, Nicol Bolas a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 2:47:11 PM UTC-4,
Matthew Woehlke wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">On
2015-06-05 14:13, Nicol Bolas wrote:
<br>
> 4) `.value()` throws the `bad_expected_access<T>`
template class. Which <br>
> means that's the type the user normally has to catch
(when not using <br>
> `exception_ptr`). Which means that catching code needs to
recognize that <br>
> the throwing code was using `expected` to do the
throwing. Why should it?
<br>
<br>
See, *this* is the point I was trying to make. *Why* does it
do that?
<br>
Should it not throw an exception indicative of *why* it
doesn't have a
<br>
value? (In particular, if the error is itself an exception,
shouldn't it
<br>
just throw that?)
<br>
<br>
At least there should be a method that does that. Perhaps even
something
<br>
short, like operator*.
<br>
</blockquote>
<div><br>
It really comes down to how you expect to use, well,
`expected`.<br>
<br>
`expected` is for local error handling. Higher level code
shouldn't have to know about it; it should be an
implementation detail to them.<br>
</div>
</div>
</blockquote>
Why do you want other use expected as you think it must be used?<br></d=
iv></blockquote><div><br>Because I may have to read, understand, and debug =
their code someday. And seeing 5 layers of code pointlessly checking and re=
turning `expected` objects, just to get it to the place where they can be d=
ealt with is not helpful in that process.<br><br>And that assumes that such=
propagation is as simple as just returning that object. For example, consi=
der an integer parsing function that returns an `expected<int, ec>`. =
Well, if the function that called it needs to propagate that error... what =
does it return?<br><br>Maybe the function doing that particular integer par=
sing returns an `array<int, 3>`, because it parses an array of intege=
rs in sequence. So you can't just return the `expected` value itself; you n=
ow have to return a new expected value: `expected<array<int, 3>, e=
c>`, which itself requires copying the error object.<br><br>And maybe th=
e next layer returns some other data structure, which itself contains `arra=
y<int, 3>`s. So it has to return `expected<DataStructure, ec>`.=
And so on up half-a-dozen layers until finally you get to the code that ca=
n actually halt the processing and deliver an error. And God forbid that on=
e of those layers happen to be a `void` function, for which `expected` isn'=
t reasonable to use.<br><br>Or you just <i>throw an exception</i> like a sa=
ne person.<br><br>The syntactic burden of propagating `expected` failures t=
hrough code is non-trivial. The syntactic burden of propagating exceptions =
is (virtually) <i>nil</i>. By contrast, the syntactic burden of `expected` =
in a local handler is close to optimal. While the syntactic burden of excep=
tions in a local context is substantial.<br><br>These are two tools, and wh=
en to use which is pretty obvious to most users. So APIs should let users p=
ick which one works best for their needs, rather than trying to force one o=
r the other.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgc=
olor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
But `value` throws an exception, and this is the right call.
When a user calls `value`, one of two things is true:<br>
<br>
1) The user has previously verified that this `expected`
instance contains a value. And thus it will never throw.<br>
<br>
2) The user has not verified that the `expected` instance
contains a value. And thus it may throw.<br>
<br>
#2 would happen in two circumstances:<br>
<br>
2a) a programming bug <br>
</div>
</div>
</blockquote>
Why. expected is always ready. Either it contains a value or the
reason why it doesn't contain it. I don't see where is the bug.<br></di=
v></blockquote><div><br>So you're saying that this:<br><br><div class=3D"pr=
ettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb=
(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-w=
ord;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify">expected</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> ec</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> t </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> fo=
o_exp</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>t</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">value</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">().</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify">stuff</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">();</span></div></code></div><br>is always =
100% reasonable and correct code that does exactly what the user intended i=
t to do? <br><br>Nonsense.<br><br>The user may simply have forgotten to put=
`if(t)` in front of that statement. <i>That</i> is the bug that 2a represe=
nts: the user <i>intended </i>to check the value (wanted to be case #1) but=
simply forgot (accidentally writing case 2). That is 2a.<br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#0000=
00">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
2b) deliberate design<br>
<br>
2c) the user wants to catch the exception thrown. This is what
you're arguing for<br>
<br>
With 2a, the program ought to terminate, since continuing
forward in the event of an obvious programming bug is usually
not a good idea.<br>
<br>
With 2b, the user has effectively <i>decided</i> that
termination is a legitimate response to this error.<br>
</div>
</div>
</blockquote>
If the user is the one that has written the call to
expected<T>::value(), what the user wants is the value and is
considering that if the value is not there this is an exceptional
case. If this user consider that it is not exceptional it should
check it before.<br></div></blockquote><div><br>I fail to see how your =
statement is in any way a response to what I said. The user deliberately ca=
uses an exception to be thrown. They either intend for that exception to be=
caught or they throw it knowing that it won't be. 2b is the case where the=
y don't catch it.<br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
OK, so... what about static analysis tools? We already have
great static tools that can detect the use of many
uninitialized values. </div>
</div>
</blockquote>
expected as optional, and I hope would variant, are never
uninitialized as these classes have default constructor.<br></div></blo=
ckquote><div><br>The bit about uninitialized values was just to explain one=
of the uses of static analysis tools to find bugs. I wasn't suggesting tha=
t these objects would be uninitialized.</div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>So it's reasonable to assume that such tools will be
expanded in the face of `optional` and `expected`, detecting
when you use them without explicitly checking that they are
real values.<br>
</div>
</div>
</blockquote>
I have the impression that you don't understand all these proposals
or maybe I don't understand what you mean.<br></div></blockquote><div><=
br>... all which proposals? There's only one (current) `expected` proposal.=
That's the one we're talking about: N4109.<br><br>What I mean is very simp=
le. This (case #1):<br><br><div class=3D"prettyprint" style=3D"background-c=
olor: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: s=
olid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint=
"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"style=
d-by-prettify">expected</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ec</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">></span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> t </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> foo_exp</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">if</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">value</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">().</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">stuff</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">();</span></div></code></div><br>=
is functional code. It cannot throw and it is correct, no matter what foo_e=
xp returns.<br><br>By contrast, this (case #2):<br><br><div class=3D"pretty=
print" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187=
, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-word;=
"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"=
color: #000;" class=3D"styled-by-prettify">expected</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> ec</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> t </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> foo_exp</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>t</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">value</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">().</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">stuff</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">();</span></div></code></div><br>is potentially da=
ngerous code. <i>Maybe</i> the user meant to throw an exception (cases 2b a=
nd 2c). Or maybe he just forgot to check the value.<br><br>A static analysi=
s tool can detect that a returned `expected` object is being used without b=
eing checked. They can do quite a lot of such checking, flowing from functi=
on to function to verify when something gets checked. Having such static an=
alysis is a <i>good thing</i>; it catches accidental bugs caused by forgett=
ing to check `expected` values.<br><br>However, any tool is only as good as=
its accuracy. Tools that miss errors are not reliable; those that return l=
ots of false positives will eventually be ignored. Therefore, users should =
endeavor to avoid writing case #2 at all. But there are legitimate reasons =
to write case #2: when you want exceptions thrown.<br><br>Therefore, to mak=
e static analysis of `expected` use as useful as possible, people who want =
exceptions thrown should... call functions that <i>throw exceptions</i>:<br=
><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 25=
0); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1p=
x; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpre=
ttyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">T t </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> foo</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>t</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">stuff</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span></div></code></div><br>`foo` here throws =
exceptions. That handles the case of 2b (where the user just wants the app =
to die on an error) and 2c (where the user wants to catch and process the e=
rror).<br><br>Because people should only be writing case 2 by accident, `.v=
alue` should (in a working application) never throw. And there's no point i=
n catching an exception if it is never thrown.<br><br>And therefore:<br></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" te=
xt=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>So what it throws is irrelevant, save for the fact that it
shouldn't be throwing something that could accidentally be
caught. So throwing a new type like `bad_expected_access` is
the right move. </div>
</div>
</blockquote>
I have the impression also that you don't want to admit that
expected can be use to store whatever the user wants to report as
error.<br></div></blockquote><div><br>The user (by which I mean the cod=
e calling the function that returned the error condition) <i>cannot</i> mak=
e that `expected` object store some data that it isn't already able to stor=
e. It can create a <i>new</i> `expected` object which stores a different er=
ror object. But it can't take an already existing one and shove data into i=
t that it's error code type is not able to store.<br><br>Also, I'm not sure=
what the information that can be stored in an `expected` object has to do =
with anything that I was talking about.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_260_261723922.1433572395194--
------=_Part_259_2045791777.1433572395194--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 06 Jun 2015 08:44:02 +0200
Raw View
Le 06/06/15 00:41, Matthew Woehlke a =C3=A9crit :
> On 2015-06-05 17:34, Vicente J. Botet Escriba wrote:
>> Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
>>> OK, so... what about static analysis tools? We already have great
>>> static tools that can detect the use of many uninitialized values.
>> expected as optional, and I hope would variant, are never uninitialized
>> as these classes have default constructor.
> Not the expected/optional itself, but the contained value.
I agreed I was not precise enough. expected is default constructible if=20
E is and optional is always default constructible.
>
> IOW, this is a (potential) error:
>
> auto x =3D function_that_returns_expected_or_optional;
> do_something(x.value());
>
> ...because you didn't check that 'x' actually *has* a value, and thus
> value() might throw.
Why is this an error and different of
do_something(function_that_can_throw());
>
> Nicol is of the opinion that one should never write code like this, even
> if throwing from the context where value() is called if there is no
> value is the intended behavior.
I don't share this opinion.
>
> I have to ask, though: in that case, why throw at all?
>
> Really, I envision expected as a 'delayed throw' mechanism. The point is
> to return an expected instead of throwing immediately, and instead delay
> *the throw that otherwise would have happened* until the user calls
> value(), thus giving a window where the user can choose to handle the
> error before an exception is thrown.
>
> If you're *not* going to implement it that way, then why even throw an
> exception? Why not just terminate the program? Or make it UB? IMO it's
> *much* more useful for expected to be an exception delaying mechanism
> than to do something that (by Nicol's assertion) is useless and
> can/should only ever result in program termination.
>
Completely agreed.
Users of expected that can not use exceptions at all couldn't use value.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 06 Jun 2015 09:02:43 +0200
Raw View
This is a multi-part message in MIME format.
--------------040703020908050301070009
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 03/06/15 07:09, Nicol Bolas a =C3=A9crit :
> After reading through various people's ideas about how to go about=20
> reporting errors from number parsing systems=20
> <https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MJIRnrc7vbo/j=
GO0zjXQrEYJ>,=20
> as well as writing a preliminary document on the variety of error=20
> reporting mechanisms=20
> <https://groups.google.com/a/isocpp.org/d/msg/std-proposals/G1YheYoGznw/7=
AuxvrJhv6gJ>=20
> in applications and libraries at present, I've come to some thoughts=20
> and conclusions on how error reporting and resolution ought to be handled=
..
>
> When I analyzed the various error reporting mechanisms, I did so along=20
> three independent axes: local error resolution, non-local error=20
> resolution, and local error ignoring. What I came to realize is that,=20
> generally speaking, in the event of an error condition, code does one=20
> of the following: the error is resolved by the code that directly=20
> generated it; the error is resolved by someone else; or the program=20
> forges ahead, blissfully unaware of an error. That may sound obvious,=20
> but it's an important point.
>
> The thing that set my mind to this was with the whole number parsing=20
> thing. In there, people made a strong case for `expected`, but these=20
> cases were always in the context of local error resolution. The=20
> function that was directly calling the `parse_integer` function would=20
> be resolving the ensuing error.
>
> The argument being that parse errors are expected; they're entirely=20
> natural. So it's expected that the local caller will field such=20
> errors, and if the caller doesn't, then the local caller has decided=20
> effectively not to care. In such an event, throwing an exception is=20
> warranted. So `expected` seems quite ideal in such circumstances; if=20
> you try to fetch the value without checking that it's there, the=20
> system will throw a wrapped error code.
>
> This seems ideal, but there are many flaws with such an approach. For=20
> example, this approach assumes that the local caller function is=20
> actually capable of resolving this kind of error. The farther up the=20
> call graph one has to search to resolve an `expected` error, the more=20
> difficult it gets to get the `expected` error where it needs to go.
>
> As an example, consider `parse_integer`. If `parse_integer` has no=20
> knowledge of filesystem IO, then it is reasonable for a user to write=20
> a function that can take a file IO object and parse integers from it.=20
> Call this `file_parse_integer`; it reads some number of non-space=20
> characters from a file stream, passes the string to `parse_integer`=20
> and then returns... what?
>
> It cannot return `expected<int, parse_error>`. Why? Because=20
> `file_parse_integer` can now fail for two /separate/ reasons: a=20
> failure to parse the characters, and a failure to /read the characters=20
> from the file stream/. The only legitimate thing that=20
> `file_parse_integer` can do is return both possibilities:=20
> `expected<int, variant<parse_error, file_error>>`. If both the file=20
> reading error and the parse error use `std::error_condition`, then at=20
> least the variant can be avoided. But regardless of how the error is=20
> returned, the direct caller is required to field all of the cases. But=20
> not just all of the parse error cases; he must field all of the file=20
> reading cases too.
>
> One might say that this is still true even if using exceptions, but I=20
> contest this for one very important reason: file reading errors=20
> usually represent a fundamentally different kind of problem than=20
> parsing errors. If an integer parse fails, that could be reasonably=20
> expected by the user and handled locally. If a file fails to read at=20
> all, this is not a problem that someone who's expecting to read an=20
> integer can resolve; it can only be effectively resolved by higher=20
> level code. The system that began this entire "parse stuff from a=20
> file" needs to be notified that it failed. How many levels high is=20
> that system? Who knows.
>
> Is it reasonable for callers of `file_parse_integer` to have to=20
> manually propagate that error all the way back?
>
> Next, one might say that this is a special case, that filesystem=20
> errors are always a different kind of thing, something which is rare=20
> and thus clearly ought to be handled by exceptions. That is not an=20
> unreasonable argument. However, there are times when parse errors can=20
> logically be treated in the same light. This would be in a file format=20
> that you the programmer have fundamental control over, who's contents=20
> are generated by internal code, not the user. To that user, parse=20
> errors are not a normal thing; they're an exceptional circumstance. If=20
> there's a parse error, this user wants to completely shut down all=20
> processing of this data, under the presumption that something truly=20
> terrible has happened in the system. Perhaps to the point of rolling=20
> back any changes made based on this data, since it must now be=20
> considered suspect.
>
> If this code were using `file_parse_integer`, it would react to a=20
> parse error in the exact same way it reacts to a filesystem error:=20
> halt the process at its source, undo anything that was done, and=20
> resume normal functionality.
>
> Is it reasonable for this user to have to manually return `expected`=20
> objects or failure error codes, just to be able to get the error where=20
> it needs to go?
>
> So in one case, we have a user who has a genuine reason to want file=20
> reading errors to be exceptions, but would probably want actual parse=20
> errors to be `expected`s. While the other use wants both of them to be=20
> exceptions.
>
> You might say that it's fine, because if you get the `expected` value=20
> without checking it, an exception will be thrown if it isn't there.=20
> And that is true.
>
> But let us consider the nature of that exception.
>
> The most recent proposal of `expected`=20
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4109.pdf>=20
> basically has two variations: one for arbitrary error code objects
I would emphasize: an arbitrary "error" not necessary std::error_code,=20
so that nobody misunderstand it.
> and one for `exception_ptr`. In the latter case, the `exception_ptr`=20
> is thrown as that exception. In the former case, a template class is=20
> thrown, based on the type for the error code used by the `expected`.
There are some open points in the proposal, e.g. we could also choose=20
the exception to be thrown.
> Now, std::error_condition can do quite a bit of stuff, based on the=20
> base `std::error_category` class it uses.
>
> However, everything that `error_condition` can do is based purely on=20
> the type of `error_category` it uses and an integer. Now, consider=20
> parsing integers. If a parse error occurs, the parsing system knows a=20
> lot of very useful information about it. It knows how many characters=20
> it successfully read. It knows exactly which character caused that=20
> error. And so forth.
>
> All of that information is /lost/ when you reduce the error to a number.
Evident.
>
> Certainly, `expected` can store something more than an=20
> `error_condition` (basically, an integer and a pointer). But if you=20
> start throwing around an `expected<int, big_giant_object>`, that's a=20
> huge cost to be paid compared to just an `int`. It's bad enough that=20
> `expected<int, error_condition>`, on 64-bit builds, is approaching a=20
> 32-byte cache-line in size; to make the object even bigger is crazy.=20
> And if you need to propagate that out of the local scope, that's a big=20
> object to be returning up the callstack.
Well all this depend on the user needs. What he needs to report as=20
error, how this error is constructed/managed. I have never used this,=20
but user could e.g. use expected<T, unique_ptr<big_giant_object>.
Or are you talking about some concrete c++ standard interface?
>
> For local error handling, providing little information is reasonable,=20
> because local code actually knows the context of the error. It knows=20
> what the input string was, the range of characters passed to=20
> `parse_integer`. Also, the return value(s) from `parse_integer` may=20
> include an offset to the parsed character, in some form.
Are we talking in general or respect to a concrete proposal?
>
> However, if an error needs to be propagated, simply inducing=20
> `expected` to throw an exception via `.value()` is... rather useless=20
> when needing to actually report a problem. Oh sure, you can use=20
> `error_condition::message` to be told something about why the text=20
> didn't parse. But you know /nothing/ about where this happened; that=20
> information was lost when the local scope returned the error code. You=20
> lose lots of very useful knowledge.
>
Have you tried to return an expected<T,=20
your_specific_case_error_with_all_the_needed_information>. What were the=20
problems with this? Performances? With which implementation of expected=20
have you tried? I'm requesting it because mine could be a poor=20
implementation(it is a POC), and there should be other implementation=20
that haven't this performance issue.
> By contrast, a `parse_integer` that natively fires off an exception=20
> can encapsulate useful information. It can say exactly where this=20
> error took place in the given string. It can even store the given=20
> string in the exception, as reference. And so forth. Information that=20
> would have been lost to the local scope can now be granted to a higher=20
> scope.
Again, why you can not report all this information with expected?
>
> This was a problem (one of many) with a suggestion that was made in=20
> another thread to have the FileSystem TS do away with exceptions=20
> /entirely/, relying solely on `expected` for error handling=20
> <https://groups.google.com/a/isocpp.org/d/msg/std-proposals/4MErTLraVDg/f=
K9pPtRgXRAJ>.=20
> The `filesystem_error` class is quite rich in information as to=20
> exactly where a problem happened, able to store and return entire=20
> `path` objects that represent parameters to various error-generating=20
> functions. For local error resolving, this seems like overkill. But=20
> for handling errors at a higher level? This is exactly the kind of=20
> information that would be lost and can be critical for finding out=20
> where a problem is.
I don' who was proposing a single interface. I remember things like, if=20
there were only an interface based on expected<T>, the user could choose=20
an exceptional interface calling value(). I remember that most of us=20
were not proposing such a single interface.
If there were only one interface based on expected, it should be based =20
expected<T> not on expected<T, error_condition>. If the performances of=20
expected<T> are proved to be not satisfactory, this could mean that we=20
have a problem on the interface, either on expected or on the single=20
choice or ... . This is why the safe option is to provide both=20
interfaces. This doesn't mean that we need to do it for all the standard=20
interfaces, the question was only related to FileSystem.
>
> Consider the prior discussed case of a `parse_integer` function, where=20
> a parse error represents a fundamental failure of the entire process=20
> of parsing this data, causing a rollback of changes made based on it.=20
> If you need to log information based on this parse error, the=20
> exception case can give you something that's actually useful. The=20
> `expected` case simply says, "Found a letter instead of a number".
Why? Why you insists in using the wrong error type?
>
> Now, you could say that all `parse_integer` could store would be=20
> information that's locally available: the string parameter. It=20
> wouldn't know how many strings had already been processed or anything.=20
> And that is true; to get more information, you would need to do some=20
> exception translation, using specific knowledge at each layer to add=20
> new information.
Maybe. As it is the case for an exception based interface that needs to=20
do a translation of exceptions.
>
> In that case, you have some local pre-processing of error information,=20
> massaging it into the most useful form for consumption. And this is=20
> starting to resemble the `expected` case, where every layer between=20
> the erroring function and the handler must know about these errors and=20
> propagate them explicitly in code. However, this way, you get to use=20
> an actual object, rather than having to fit things into an=20
> `error_condition`. Yes, `expected` could use any object; however, as=20
> previously discussed, if multiple paths of code need to propagate=20
> multiple errors up the same function, `error_condition` is pretty much=20
> the only sane way to go. Unless you like sorting through `variants`.
Are you against variants errors ?
>
> The exception case is so much cleaner, even with having to do=20
> translation at various layers. Only layers that actually do=20
> translation need to be involved in that process; otherwise, the code=20
> is clean.
Clean is subjective.
>
> And then there are things that `expected` flat-out cannot handle or=20
> handles very poorly.
>
> The first is any function that doesn't return a value. Oh yes,=20
> `expected<void, ec>` exists. But it would be rather... foolish to=20
> expect everyone to do that. Uniformly.
Are you talking of the standard or of an hypothetical user?
>
> The same applies to any function that returns a value that most users=20
> will drop on the floor. `filesystem::create_directory` is a good=20
> example. Most people will just assume it succeeded. But only in the=20
> exception case will they be forced to confront the possibility of failure=
..
There is another open point in the Expected proposal. Some have=20
requested that the expected destructor terminates if the value has not=20
been obtained. I think that there is merit in this approach. This=20
requirement makes the class a little bit more complex, but the=20
robustness gain is considerable. Maybe this could be a QOI.
>
> To be fair to `expected`, the latter two can be helped via external=20
> tools. It would be possible, particularly with Clang, to write a tool=20
> that scans for `expected` return values that are discarded.
As we can discard error codes, isn't it?
>
> The more extreme case is object construction, for which the C++=20
> standard has no solution other than exceptions. Options like=20
> `expected(in_place_t)` don't really work. You lose "uniform"=20
> initialization syntax, as you can't access the initializer_list=20
> constructor with {}. It's a nice try, and is necessary for=20
> initializing immobile types. But it doesn't work nearly as well as a=20
> straight constructor. And most importantly of all, it doesn't actually=20
> capture any exceptions thrown by `T`'s constructor.
You are right, but error codes doesn't work here neither.
expected works better with factories than with constructors that can throw.
struct X {
static expected<X> makeExpected(...);
static X make(...); // can throw
X(...); // can throw
// ...
};
>
> That all brings me to a number of conclusions:
>
> 1) Exceptions work best in non-local error handling contexts. Local=20
> error handling best works via `expected`, except where `expected`=20
> cannot be used
As for example?
> or is poor at the job.
As for example?
>
> 2) The difference between local and non-local handling /cannot be=20
> known to the library/. It may guess and hope, but there are usually=20
> legitimate cases where a user might handle errors one way or the other.
>
> 3) Where possible, allow the user to decide whether errors are handled=20
> locally or not. As such, functions that error should have two=20
> versions: one that throws and one that uses `expected`.
>
I completely agree. This situation seems better to me than the current=20
one that makes use of output parameter errors.
An alternative that I have not explored/implemented yet is to have an=20
overloaded function with a first parameter that states the error=20
mechanism to be used.
This could be similar to the asynchronous functions and executors, or=20
the parallelism TS.
The result type of the function would depend on this first parameter.
T f(throws, ...)
expected<T> f(no_throws, ...)
One of the problems with this approach is that the number of arguments=20
of the signature changes, an so we could need to bind the fist argument=20
to make it possible to use these functions were this first argument is=20
not expected.
There is yet an additional alternative to share a common implementation=20
with a single parameterized implementation. All of us know however that=20
making generic code add some additional burden.
template <class ErrorMechanism>
ErrorMechanism::result<T> f(ErrorMechanism, ...);
throws::result<T> is T
no_throws::result<T> is expected<T>
The body of the function can finish with a value of type T using
return t;
as far as the result type is convertible from T
It can return an error using the ErrorMechanism
return ErrorMechanism::error(e);
as far as result type is convertible from ErrorMechanism::error(e) when=20
ErrorMechanism::error(e) doesn't throws
throws::error(e) will throw e.
no_throws::error(e) will return unexpected(e)
The ErrorMechanism abstraction could also support a way to report short=20
and efficient errors and exceptions
return ErrorMechanism::error(my_error_code, MyException(....));
In order to ensure that only one of them is evaluated we will need some=20
kind of lazy evaluation mechanism as others are proposing.
Waiting for that we could use a conditional expression
return ErrorMechanism::supports_exceptions
? ErrorMechanism::error(MyException(....));
: ErrorMechanism::error(my_error_code)
;
The error propagation would be done using the await operator.
The error recovery using value() or pattern matching or the specific=20
catch_error() function.
Note that executors cold be seen as a specific ErrorMechanism.
So maybe the template parameter ErrorMechanism becomes something like an=20
ExecutionPolicy or whatever name is more approppriated that gouverns the=20
synchronous/asynchronous aspect and how errors are propagated.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------040703020908050301070009
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 03/06/15 07:09, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">After reading through various people's ideas about
how to go about <a moz-do-not-send=3D"true"
href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MJIRnrc7=
vbo/jGO0zjXQrEYJ">reporting
errors from number parsing systems</a>, as well as writing a <a
moz-do-not-send=3D"true"
href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-proposals/G1YheYoG=
znw/7AuxvrJhv6gJ">preliminary
document on the variety of error reporting mechanisms</a> in
applications and libraries at present, I've come to some
thoughts and conclusions on how error reporting and resolution
ought to be handled.<br>
<br>
When I analyzed the various error reporting mechanisms, I did so
along three independent axes: local error resolution, non-local
error resolution, and local error ignoring. What I came to
realize is that, generally speaking, in the event of an error
condition, code does one of the following: the error is resolved
by the code that directly generated it; the error is resolved by
someone else; or the program forges ahead, blissfully unaware of
an error. That may sound obvious, but it's an important point.<br>
<br>
The thing that set my mind to this was with the whole number
parsing thing. In there, people made a strong case for
`expected`, but these cases were always in the context of local
error resolution. The function that was directly calling the
`parse_integer` function would be resolving the ensuing error.<br>
<br>
The argument being that parse errors are expected; they're
entirely natural. So it's expected that the local caller will
field such errors, and if the caller doesn't, then the local
caller has decided effectively not to care. In such an event,
throwing an exception is warranted. So `expected` seems quite
ideal in such circumstances; if you try to fetch the value
without checking that it's there, the system will throw a
wrapped error code.<br>
<br>
This seems ideal, but there are many flaws with such an
approach. For example, this approach assumes that the local
caller function is actually capable of resolving this kind of
error. The farther up the call graph one has to search to
resolve an `expected` error, the more difficult it gets to get
the `expected` error where it needs to go.<br>
<br>
As an example, consider `parse_integer`. If `parse_integer` has
no knowledge of filesystem IO, then it is reasonable for a user
to write a function that can take a file IO object and parse
integers from it. Call this `file_parse_integer`; it reads some
number of non-space characters from a file stream, passes the
string to `parse_integer` and then returns... what?<br>
<br>
It cannot return `expected<int, parse_error>`. Why?
Because `file_parse_integer` can now fail for two <i>separate</i>
reasons: a failure to parse the characters, and a failure to <i>rea=
d
the characters from the file stream</i>. The only legitimate
thing that `file_parse_integer` can do is return both
possibilities: `expected<int, variant<parse_error,
file_error>>`. If both the file reading error and the
parse error use `std::error_condition`, then at least the
variant can be avoided. But regardless of how the error is
returned, the direct caller is required to field all of the
cases. But not just all of the parse error cases; he must field
all of the file reading cases too.<br>
<br>
One might say that this is still true even if using exceptions,
but I contest this for one very important reason: file reading
errors usually represent a fundamentally different kind of
problem than parsing errors. If an integer parse fails, that
could be reasonably expected by the user and handled locally. If
a file fails to read at all, this is not a problem that someone
who's expecting to read an integer can resolve; it can only be
effectively resolved by higher level code. The system that began
this entire "parse stuff from a file" needs to be notified that
it failed. How many levels high is that system? Who knows.<br>
<br>
Is it reasonable for callers of `file_parse_integer` to have to
manually propagate that error all the way back?<br>
<br>
Next, one might say that this is a special case, that filesystem
errors are always a different kind of thing, something which is
rare and thus clearly ought to be handled by exceptions. That is
not an unreasonable argument. However, there are times when
parse errors can logically be treated in the same light. This
would be in a file format that you the programmer have
fundamental control over, who's contents are generated by
internal code, not the user. To that user, parse errors are not
a normal thing; they're an exceptional circumstance. If there's
a parse error, this user wants to completely shut down all
processing of this data, under the presumption that something
truly terrible has happened in the system. Perhaps to the point
of rolling back any changes made based on this data, since it
must now be considered suspect.<br>
<br>
If this code were using `file_parse_integer`, it would react to
a parse error in the exact same way it reacts to a filesystem
error: halt the process at its source, undo anything that was
done, and resume normal functionality.<br>
<br>
Is it reasonable for this user to have to manually return
`expected` objects or failure error codes, just to be able to
get the error where it needs to go?<br>
<br>
So in one case, we have a user who has a genuine reason to want
file reading errors to be exceptions, but would probably want
actual parse errors to be `expected`s. While the other use wants
both of them to be exceptions.<br>
<br>
You might say that it's fine, because if you get the `expected`
value without checking it, an exception will be thrown if it
isn't there. And that is true.<br>
<br>
But let us consider the nature of that exception.<br>
<br>
The <a moz-do-not-send=3D"true"
href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n=
4109.pdf">most
recent proposal of `expected`</a> basically has two
variations: one for arbitrary error code objects </div>
</blockquote>
I would emphasize: an arbitrary "error" not necessary
std::error_code, so that nobody misunderstand it.<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">and one for `exception_ptr`. In the latter case,
the `exception_ptr` is thrown as that exception. In the former
case, a template class is thrown, based on the type for the
error code used by the `expected`. </div>
</blockquote>
There are some open points in the proposal, e.g. we could also
choose the exception to be thrown.<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">Now, std::error_condition can do quite a bit of
stuff, based on the base `std::error_category` class it uses.<br>
<br>
However, everything that `error_condition` can do is based
purely on the type of `error_category` it uses and an integer.
Now, consider parsing integers. If a parse error occurs, the
parsing system knows a lot of very useful information about it.
It knows how many characters it successfully read. It knows
exactly which character caused that error. And so forth.<br>
<br>
All of that information is <i>lost</i> when you reduce the
error to a number.<br>
</div>
</blockquote>
Evident.<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
Certainly, `expected` can store something more than an
`error_condition` (basically, an integer and a pointer). But if
you start throwing around an `expected<int,
big_giant_object>`, that's a huge cost to be paid compared to
just an `int`. It's bad enough that `expected<int,
error_condition>`, on 64-bit builds, is approaching a 32-byte
cache-line in size; to make the object even bigger is crazy. And
if you need to propagate that out of the local scope, that's a
big object to be returning up the callstack.<br>
</div>
</blockquote>
Well all this depend on the user needs. What he needs to report as
error, how this error is constructed/managed. I have never used
this, but user could e.g. use expected<T,
unique_ptr<big_giant_object>.<br>
<br>
Or are you talking about some concrete c++ standard interface? <br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
For local error handling, providing little information is
reasonable, because local code actually knows the context of the
error. It knows what the input string was, the range of
characters passed to `parse_integer`. Also, the return value(s)
from `parse_integer` may include an offset to the parsed
character, in some form.<br>
</div>
</blockquote>
Are we talking in general or respect to a concrete proposal? <br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
However, if an error needs to be propagated, simply inducing
`expected` to throw an exception via `.value()` is... rather
useless when needing to actually report a problem. Oh sure, you
can use `error_condition::message` to be told something about
why the text didn't parse. But you know <i>nothing</i> about
where this happened; that information was lost when the local
scope returned the error code. You lose lots of very useful
knowledge.<br>
<br>
</div>
</blockquote>
Have you tried to return an expected<T,
your_specific_case_error_with_all_the_needed_information>. What
were the problems with this? Performances? With which implementation
of expected have you tried? I'm requesting it because mine could be
a poor implementation(it is a POC), and there should be other
implementation that haven't this performance issue.<br>
<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">By contrast, a `parse_integer` that natively fires
off an exception can encapsulate useful information. It can say
exactly where this error took place in the given string. It can
even store the given string in the exception, as reference. And
so forth. Information that would have been lost to the local
scope can now be granted to a higher scope.<br>
</div>
</blockquote>
Again, why you can not report all this information with expected?<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
This was a problem (one of many) with a suggestion that was made
in another thread to have <a moz-do-not-send=3D"true"
href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-proposals/4MErTLra=
VDg/fK9pPtRgXRAJ">the
FileSystem TS do away with exceptions <i>entirely</i>,
relying solely on `expected` for error handling</a>. The
`filesystem_error` class is quite rich in information as to
exactly where a problem happened, able to store and return
entire `path` objects that represent parameters to various
error-generating functions. For local error resolving, this
seems like overkill. But for handling errors at a higher level?
This is exactly the kind of information that would be lost and
can be critical for finding out where a problem is.<br>
</div>
</blockquote>
I don' who was proposing a single interface. I remember things like,
if there were only an interface based on expected<T>, the user
could choose an exceptional interface calling value(). I remember
that most of us were not proposing such a single interface.<br>
<br>
If there were only one interface based on expected, it should be
based=C2=A0 expected<T> not on expected<T, error_condition>=
..
If the performances of expected<T> are proved to be not
satisfactory, this could mean that we have a problem on the
interface, either on expected or on the single choice=C2=A0 or ... . Th=
is
is why the safe option is to provide both interfaces. This doesn't
mean that we need to do it for all the standard interfaces, the
question was only related to FileSystem.<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
Consider the prior discussed case of a `parse_integer` function,
where a parse error represents a fundamental failure of the
entire process of parsing this data, causing a rollback of
changes made based on it. If you need to log information based
on this parse error, the exception case can give you something
that's actually useful. The `expected` case simply says, "Found
a letter instead of a number".<br>
</div>
</blockquote>
Why? Why you insists in using the wrong error type?<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
Now, you could say that all `parse_integer` could store would be
information that's locally available: the string parameter. It
wouldn't know how many strings had already been processed or
anything. And that is true; to get more information, you would
need to do some exception translation, using specific knowledge
at each layer to add new information.<br>
</div>
</blockquote>
Maybe. As it is the case for an exception based interface that needs
to do a translation of exceptions.<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
In that case, you have some local pre-processing of error
information, massaging it into the most useful form for
consumption. And this is starting to resemble the `expected`
case, where every layer between the erroring function and the
handler must know about these errors and propagate them
explicitly in code. However, this way, you get to use an actual
object, rather than having to fit things into an
`error_condition`. Yes, `expected` could use any object;
however, as previously discussed, if multiple paths of code need
to propagate multiple errors up the same function,
`error_condition` is pretty much the only sane way to go. Unless
you like sorting through `variants`.<br>
</div>
</blockquote>
Are you against variants errors ?<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
The exception case is so much cleaner, even with having to do
translation at various layers. Only layers that actually do
translation need to be involved in that process; otherwise, the
code is clean.<br>
</div>
</blockquote>
Clean is subjective.<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
And then there are things that `expected` flat-out cannot handle
or handles very poorly.<br>
<br>
The first is any function that doesn't return a value. Oh yes,
`expected<void, ec>` exists. But it would be rather...
foolish to expect everyone to do that. Uniformly.<br>
</div>
</blockquote>
Are you talking of the standard or of an hypothetical user? <br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
The same applies to any function that returns a value that most
users will drop on the floor. `filesystem::create_directory` is
a good example. Most people will just assume it succeeded. But
only in the exception case will they be forced to confront the
possibility of failure.<br>
</div>
</blockquote>
There is another open point in the Expected proposal. Some have
requested that the expected destructor terminates if the value has
not been obtained. I think that there is merit in this approach.
This requirement makes the class a little bit more complex, but the
robustness gain is considerable. Maybe this could be a QOI.<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
To be fair to `expected`, the latter two can be helped via
external tools. It would be possible, particularly with Clang,
to write a tool that scans for `expected` return values that are
discarded.<br>
</div>
</blockquote>
As we can discard error codes, isn't it?<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
The more extreme case is object construction, for which the C++
standard has no solution other than exceptions. Options like
`expected(in_place_t)` don't really work. You lose "uniform"
initialization syntax, as you can't access the initializer_list
constructor with {}. It's a nice try, and is necessary for
initializing immobile types. But it doesn't work nearly as well
as a straight constructor. And most importantly of all, it
doesn't actually capture any exceptions thrown by `T`'s
constructor.<br>
</div>
</blockquote>
You are right, but error codes doesn't work here neither. <br>
<br>
expected works better with factories than with constructors that can
throw.<br>
<br>
struct X {<br>
=C2=A0=C2=A0=C2=A0 static expected<X> makeExpected(...);<br>
=C2=A0=C2=A0=C2=A0 static X make(...); // can throw<br>
=C2=A0=C2=A0=C2=A0 X(...); // can throw<br>
=C2=A0=C2=A0=C2=A0 // ...<br>
};<br>
<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
That all brings me to a number of conclusions:<br>
<br>
1) Exceptions work best in non-local error handling contexts.
Local error handling best works via `expected`, except where
`expected` cannot be used </div>
</blockquote>
As for example?<br>
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">or is poor at the job.<br>
</div>
</blockquote>
As for example?
<blockquote
cite=3D"mid:b171ba85-b2cf-436a-9fa6-11525c186498@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
2) The difference between local and non-local handling <i>cannot
be known to the library</i>. It may guess and hope, but there
are usually legitimate cases where a user might handle errors
one way or the other.<br>
<br>
3) Where possible, allow the user to decide whether errors are
handled locally or not. As such, functions that error should
have two versions: one that throws and one that uses `expected`.<br=
>
</div>
<br>
</blockquote>
I completely agree. This situation seems better to me than the
current one that makes use of output parameter errors.<br>
<br>
An alternative that I have not explored/implemented yet is to have
an overloaded function with a first parameter that states the error
mechanism to be used.<br>
This could be similar to the asynchronous functions and executors,
or the parallelism TS.<br>
<br>
The result type of the function would depend on this first
parameter.<br>
<br>
=C2=A0=C2=A0=C2=A0 T f(throws, ...)<br>
=C2=A0=C2=A0=C2=A0 expected<T> f(no_throws, ...)<br>
<br>
One of the problems with this approach is that the number of
arguments of the signature changes, an so we could need to bind the
fist argument to make it possible to use these functions were this
first argument is not expected.<br>
<br>
There is yet an additional alternative to share a common
implementation with a single parameterized implementation. All of us
know however that making generic code add some additional burden.<br>
<br>
=C2=A0=C2=A0=C2=A0 template <class ErrorMechanism><br>
=C2=A0=C2=A0=C2=A0 ErrorMechanism::result<T> f(ErrorMechanism, ..=
..);<br>
<br>
throws::result<T> is T<br>
no_throws::result<T> is expected<T><br>
<br>
The body of the function can finish with a value of type T using<br>
<br>
=C2=A0=C2=A0=C2=A0 return t;<br>
<br>
as far as the result type is convertible from T<br>
<br>
<br>
It can return an error using the ErrorMechanism<br>
<br>
=C2=A0=C2=A0=C2=A0 return ErrorMechanism::error(e);<br>
<br>
as far as result type is convertible from ErrorMechanism::error(e)
when ErrorMechanism::error(e) doesn't throws<br>
<br>
throws::error(e) will throw e.<br>
no_throws::error(e) will return unexpected(e)<br>
<br>
<br>
The ErrorMechanism abstraction could also support a way to report
short and efficient errors and exceptions<br>
<br>
=C2=A0=C2=A0=C2=A0 return ErrorMechanism::error(my_error_code, MyExcept=
ion(....));<br>
<br>
In order to ensure that only one of them is evaluated we will need
some kind of lazy evaluation mechanism as others are proposing.<br>
<br>
Waiting for that we could use a conditional expression<br>
<br>
=C2=A0=C2=A0=C2=A0 return ErrorMechanism::supports_exceptions <br>
=C2=A0=C2=A0=C2=A0 ? ErrorMechanism::error(MyException(....));<br>
=C2=A0=C2=A0=C2=A0 : ErrorMechanism::error(my_error_code)<br>
=C2=A0=C2=A0=C2=A0 ;<br>
<br>
The error propagation would be done using the await operator.<br>
<br>
The error recovery using value() or pattern matching or the specific
catch_error() function.<br>
<br>
Note that executors cold be seen as a specific ErrorMechanism.<br>
<br>
So maybe the template parameter ErrorMechanism becomes something
like an ExecutionPolicy or whatever name is more approppriated that
gouverns the synchronous/asynchronous aspect and how errors are
propagated.<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------040703020908050301070009--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 06 Jun 2015 09:08:26 +0200
Raw View
This is a multi-part message in MIME format.
--------------040003090700040501020102
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 05/06/15 20:13, Nicol Bolas a =C3=A9crit :
> On Friday, June 5, 2015 at 1:40:33 PM UTC-4, Matthew Woehlke wrote:
>
> On 2015-06-05 12:01, Nicol Bolas wrote:
> > On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew Woehlke
> wrote:
> >> I think we need expected, but I don't think we should be promoting
> >> it as the One True Method for global error handling. Developers
> >> should continue to use their preferred method for error
> >> propagation. As much as possible, expected should be friendly to
> >> callers that want to turn errors into exceptions.
> >
> > You were doing so well, right up until the last sentence.
>
> So we should *not* make expected as friendly as possible for callers
> that are going to turn it into an exception?
>
> > The choice needs to be made by the caller, yes. But the choice
> should be
> > made by calling a function that throws exceptions, not by
> calling some
> > member of an `expected`. By then, you've already lost some
> information that
> > the function had about the actual error.
>
> Why? Why does returning an expected necessarily mean that information
> *must* be lost?
>
> As usual, I think you are missing the point. *If and where*
> expected can
> be used without losing information, is there still a strong
> motivation
> to have a throwing variant?
>
>
> Yes: API consistency.
>
> There will be APIs where exception information can be lost, and there=20
> will be APIs were information cannot be lost. But that is effectively=20
> an implementation detail, one that should not be visible to the user.=20
> The user shouldn't have to know or care that this particular function=20
> throws special exceptions.
>
>
> > Oh, you can have `.value()` throw if it doesn't hold a value;
> that's fine.
> > But throwing in such a case should not represent the same thing
> as the
> > function actually throwing. It instead represents a caller of the
> > `expected` version who didn't do what he was supposed to do.
>
> Again, why? My understanding is that it is intended that expected be
> usable by callers that just want exceptions, by simply assuming
> that the
> expected always has a value. Yes, the exact point at which the
> exception
> is thrown is changed (trivially), but I fail to see why that
> should matter.
>
> Look at it differently. Let's say I have a function:
>
> expected<T, exception_ptr> foo_expected();
>
>
> Let's further say that the exception is exactly what foo_throws()
> would
> throw, i.e. no information is lost. Why should I then not write:
>
> T foo_throws() { return foo_expected().value(); }
>
>
> Because you probably lose elision in this circumstance.
I don't understand what you mean. Could develop this?
>
> And further, if the above is inline, how is it in any way
> different from
> writing at the call site:
>
> foo().value()
>
>
> Because:
>
> 1) I don't have to see the syntactically useless `.value()` in my code.
If the function return expected you would have the option
await f() ?
>
> 2) API consistency. `foo()` throws; `foo_exp()` returns an `expected`.=20
> Always (unless _exp doesn't make sense for a particular function).
>
> 3) Why should `foo_exp` return `exception_ptr` at all? Why should it=20
> construct such a heavy-weight object to contain information the=20
> majority of which the direct caller of `foo_exp` knows already? Again,=20
> going back to Filesystem, the filesyste_error exception contains=20
> `path` parameters; why should a Filesystem function that returns=20
> `expected` provide access to parameters that the caller already knows?
>
> 4) `.value()` throws the `bad_expected_access<T>` template class.=20
> Which means that's the type the user normally has to catch (when not=20
> using `exception_ptr`). Which means that catching code needs to=20
> recognize that the throwing code was using `expected` to do the=20
> throwing. Why should it?
Why not? future<T> behaves this way. Moving from a function that returns=20
expected<T> to a function that returns future<T> will have not too much=20
consequences on the caller side (if we reach to remove the syntactical=20
differences - get versus value - or if we provide a monadic interface=20
and both classes are mapped to model this concept).
>
> As a throwing interface, `expected` is sub-optimal. And this is as it=20
> should be. Let the caller decide by picking the proper function to=20
> call, not by what `expected` throws.
I guess that we are talking here about a concrete case of C++ standard=20
library interface, e.g. for FileSystem and not of a general case (sorry=20
if I missed the context of the thread).
Vicente
P.S. I have started the thread from the beginning now.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------040003090700040501020102
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 05/06/15 20:13, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:aaed4b27-37e3-48fa-aea1-c8e596447ccf@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 1:40:33 PM UTC-4,
Matthew Woehlke wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On
2015-06-05 12:01, Nicol Bolas wrote:
<br>
> On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew
Woehlke wrote:
<br>
>> I think we need expected, but I don't think we should
be promoting
<br>
>> it as the One True Method for global error handling.
Developers
<br>
>> should continue to use their preferred method for
error <br>
>> propagation. As much as possible, expected should be
friendly to
<br>
>> callers that want to turn errors into exceptions.
<br>
> <br>
> You were doing so well, right up until the last sentence.
<br>
<br>
So we should *not* make expected as friendly as possible for
callers
<br>
that are going to turn it into an exception?
<br>
<br>
> The choice needs to be made by the caller, yes. But the
choice should be <br>
> made by calling a function that throws exceptions, not by
calling some <br>
> member of an `expected`. By then, you've already lost
some information that <br>
> the function had about the actual error.
<br>
<br>
Why? Why does returning an expected necessarily mean that
information
<br>
*must* be lost?
<br>
<br>
As usual, I think you are missing the point. *If and where*
expected can
<br>
be used without losing information, is there still a strong
motivation
<br>
to have a throwing variant?</blockquote>
<div><br>
Yes: API consistency.<br>
<br>
There will be APIs where exception information can be lost,
and there will be APIs were information cannot be lost. But
that is effectively an implementation detail, one that should
not be visible to the user. The user shouldn't have to know or
care that this particular function throws special exceptions.<br>
<br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>
> Oh, you can have `.value()` throw if it doesn't hold a
value; that's fine. <br>
> But throwing in such a case should not represent the same
thing as the <br>
> function actually throwing. It instead represents a
caller of the <br>
> `expected` version who didn't do what he was supposed to
do.
<br>
<br>
Again, why? My understanding is that it is intended that
expected be
<br>
usable by callers that just want exceptions, by simply
assuming that the
<br>
expected always has a value. Yes, the exact point at which the
exception
<br>
is thrown is changed (trivially), but I fail to see why that
should matter.
<br>
<br>
Look at it differently. Let's say I have a function:
<br>
<br>
=C2=A0 expected<T, exception_ptr> foo_expected(); <br>
</blockquote>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>
Let's further say that the exception is exactly what
foo_throws() would
<br>
throw, i.e. no information is lost. Why should I then not
write:
<br>
<br>
=C2=A0 T foo_throws() { return foo_expected().value(); }<br>
</blockquote>
<div><br>
Because you probably lose elision in this circumstance.<br>
</div>
</div>
</blockquote>
I don't understand what you mean. Could develop this?<br>
<blockquote
cite=3D"mid:aaed4b27-37e3-48fa-aea1-c8e596447ccf@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
And further, if the above is inline, how is it in any way
different from
<br>
writing at the call site:
<br>
<br>
=C2=A0 foo().value()<br>
</blockquote>
<div><br>
Because:<br>
<br>
1) I don't have to see the syntactically useless `.value()` in
my code.<br>
</div>
</div>
</blockquote>
If the function return expected you would have the option<br>
<br>
=C2=A0=C2=A0=C2=A0 await f() ?<br>
<blockquote
cite=3D"mid:aaed4b27-37e3-48fa-aea1-c8e596447ccf@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
2) API consistency. `foo()` throws; `foo_exp()` returns an
`expected`. Always (unless _exp doesn't make sense for a
particular function).<br>
<br>
3) Why should `foo_exp` return `exception_ptr` at all? Why
should it construct such a heavy-weight object to contain
information the majority of which the direct caller of
`foo_exp` knows already? Again, going back to Filesystem, the
filesyste_error exception contains `path` parameters; why
should a Filesystem function that returns `expected` provide
access to parameters that the caller already knows?<br>
<br>
4) `.value()` throws the `bad_expected_access<T>`
template class. Which means that's the type the user normally
has to catch (when not using `exception_ptr`). Which means
that catching code needs to recognize that the throwing code
was using `expected` to do the throwing. Why should it?<br>
</div>
</div>
</blockquote>
Why not? future<T> behaves this way. Moving from a function
that returns expected<T> to a function that returns
future<T> will have not too much consequences on the caller
side (if we reach to remove the syntactical differences - get versus
value - or if we provide a monadic interface and both classes are
mapped to model this concept). <br>
<br>
<blockquote
cite=3D"mid:aaed4b27-37e3-48fa-aea1-c8e596447ccf@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
As a throwing interface, `expected` is sub-optimal. And this
is as it should be. Let the caller decide by picking the
proper function to call, not by what `expected` throws.<br>
</div>
</div>
</blockquote>
I guess that we are talking here about a concrete case of=C2=A0 C++
standard library interface, e.g. for FileSystem and not of a general
case (sorry if I missed the context of the thread).<br>
<br>
Vicente<br>
<br>
P.S. I have started the thread from the beginning now.<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------040003090700040501020102--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 6 Jun 2015 00:19:52 -0700 (PDT)
Raw View
------=_Part_336_1752173093.1433575192745
Content-Type: multipart/alternative;
boundary="----=_Part_337_329922740.1433575192745"
------=_Part_337_329922740.1433575192745
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, June 5, 2015 at 6:42:30 PM UTC-4, Matthew Woehlke wrote:
>
> On 2015-06-05 17:34, Vicente J. Botet Escriba wrote:=20
> > Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :=20
> >> OK, so... what about static analysis tools? We already have great=20
> >> static tools that can detect the use of many uninitialized values.=20
> >=20
> > expected as optional, and I hope would variant, are never uninitialized=
=20
> > as these classes have default constructor.=20
>
> Not the expected/optional itself, but the contained value.=20
>
> IOW, this is a (potential) error:=20
>
> auto x =3D function_that_returns_expected_or_optional;=20
> do_something(x.value());=20
>
> ...because you didn't check that 'x' actually *has* a value, and thus=20
> value() might throw.=20
>
> Nicol is of the opinion that one should never write code like this, even=
=20
> if throwing from the context where value() is called if there is no=20
> value is the intended behavior.=20
>
> I have to ask, though: in that case, why throw at all?
>
Because "wrong" doesn't necessarily mean "shouldn't be allowed."
Sometimes, some piece of code winds up with an `expected` that doesn't have=
=20
its value, and that code's precondition is that it should have a value. The=
=20
code doesn't check it because it shouldn't be possible, but maybe they've=
=20
done something that defeats the static analysis tool (or their compiler=20
isn't smart enough to find it for them). But for whatever reason, this code=
=20
bug has happened.
If that happens, the application should terminate, but in a way that can be=
=20
traced back at least to the point where `value` was called. Throwing an=20
uncaught exception is a reasonable way to do that.
Really, I envision expected as a 'delayed throw' mechanism. The point is=20
> to return an expected instead of throwing immediately, and instead delay=
=20
> *the throw that otherwise would have happened* until the user calls=20
> value(), thus giving a window where the user can choose to handle the=20
> error before an exception is thrown.
>
Well, a lot of the functional programming crowd in this thread seems to=20
think that `expected` objects should be flying up the call-stack via=20
`await` shenanigans or whatever. So there's some disagreement here as to=20
how `expected` ought to be used.
I see `expected` as how I described it in my look at it: an alternate way=
=20
to pass an error directly to the local calling scope.
There are several problems with thinking of `expected` as merely a delayed=
=20
throwing mechanic. Part of it has to do with what goes into the error code=
=20
portion.
As previously stated, exceptions often need rich information, since they=20
are usually processed far from their invocation site. `expected` objects=20
are usually processed close enough that the local code can get much of this=
=20
information themselves. In those cases, a simple std::error_condition is=20
often sufficient.
Something like `exception_ptr` is completely opaque; the only thing you can=
=20
do with that is throw it. You can't inspect it to find out which exception=
=20
was captured or anything. Even a shared pointer to some object is=20
problematic because you're having to allocate memory just to pass an error.
Because of all of that, exceptions thrown by `.value` exceptions will=20
oftentimes be of limited use compared to exceptions that would natively be=
=20
thrown. Couple that with the static analysis issues, and you have a pretty=
=20
good argument for good coding practices to suggest avoiding the capture of=
=20
any exception thrown by `.value()`.
=20
> If you're *not* going to implement it that way, then why even throw an=20
> exception? Why not just terminate the program? Or make it UB? IMO it's=20
> *much* more useful for expected to be an exception delaying mechanism=20
> than to do something that (by Nicol's assertion) is useless and=20
> can/should only ever result in program termination.=20
>
> --=20
> Matthew=20
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_337_329922740.1433575192745
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 5, 2015 at 6:42:30 PM UTC-4, Matthew Woehl=
ke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2015-06-05 17:34, =
Vicente J. Botet Escriba wrote:
<br>> Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
<br>>> OK, so... what about static analysis tools? We already have gr=
eat
<br>>> static tools that can detect the use of many uninitialized val=
ues.
<br>>
<br>> expected as optional, and I hope would variant, are never uninitia=
lized
<br>> as these classes have default constructor.
<br>
<br>Not the expected/optional itself, but the contained value.
<br>
<br>IOW, this is a (potential) error:
<br>
<br> auto x =3D function_that_returns_<wbr>expected_or_optional;
<br> do_something(x.value());
<br>
<br>...because you didn't check that 'x' actually *has* a value, and thus
<br>value() might throw.
<br>
<br>Nicol is of the opinion that one should never write code like this, eve=
n
<br>if throwing from the context where value() is called if there is no
<br>value is the intended behavior.
<br>
<br>I have to ask, though: in that case, why throw at all?<br></blockquote>=
<div><br>Because "wrong" doesn't necessarily mean "shouldn't be allowed."<b=
r><br>Sometimes, some piece of code winds up with an `expected` that doesn'=
t have its value, and that code's precondition is that it should have a val=
ue. The code doesn't check it because it shouldn't be possible, but maybe t=
hey've done something that defeats the static analysis tool (or their compi=
ler isn't smart enough to find it for them). But for whatever reason, this =
code bug has happened.<br><br>If that happens, the application should termi=
nate, but in a way that can be traced back at least to the point where `val=
ue` was called. Throwing an uncaught exception is a reasonable way to do th=
at.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
Really, I envision expected as a 'delayed throw' mechanism. The point is
<br>to return an expected instead of throwing immediately, and instead dela=
y
<br>*the throw that otherwise would have happened* until the user calls
<br>value(), thus giving a window where the user can choose to handle the
<br>error before an exception is thrown.<br></blockquote><div><br>Well, a l=
ot of the functional programming crowd in this thread seems to think that `=
expected` objects should be flying up the call-stack via `await` shenanigan=
s or whatever. So there's some disagreement here as to how `expected` ought=
to be used.<br><br>I see `expected` as how I described it in my look at it=
: an alternate way to pass an error directly to the local calling scope.<br=
><br>There are several problems with thinking of `expected` as merely a del=
ayed throwing mechanic. Part of it has to do with what goes into the error =
code portion.<br><br>As previously stated, exceptions often need rich infor=
mation, since they are usually processed far from their invocation site. `e=
xpected` objects are usually processed close enough that the local code can=
get much of this information themselves. In those cases, a simple std::err=
or_condition is often sufficient.<br><br>Something like `exception_ptr` is =
completely opaque; the only thing you can do with that is throw it. You can=
't inspect it to find out which exception was captured or anything. Even a =
shared pointer to some object is problematic because you're having to alloc=
ate memory just to pass an error.<br><br>Because of all of that, exceptions=
thrown by `.value` exceptions will oftentimes be of limited use compared t=
o exceptions that would natively be thrown. Couple that with the static ana=
lysis issues, and you have a pretty good argument for good coding practices=
to suggest avoiding the capture of any exception thrown by `.value()`.<br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">If you're *not* go=
ing to implement it that way, then why even throw an
<br>exception? Why not just terminate the program? Or make it UB? IMO it's
<br>*much* more useful for expected to be an exception delaying mechanism
<br>than to do something that (by Nicol's assertion) is useless and
<br>can/should only ever result in program termination.
<br>
<br>--=20
<br>Matthew
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_337_329922740.1433575192745--
------=_Part_336_1752173093.1433575192745--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 6 Jun 2015 00:24:31 -0700 (PDT)
Raw View
------=_Part_314_1281707761.1433575471831
Content-Type: multipart/alternative;
boundary="----=_Part_315_253876070.1433575471831"
------=_Part_315_253876070.1433575471831
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, June 6, 2015 at 3:08:28 AM UTC-4, Vicente J. Botet Escriba=20
wrote:
>
> Le 05/06/15 20:13, Nicol Bolas a =C3=A9crit :
> =20
> On Friday, June 5, 2015 at 1:40:33 PM UTC-4, Matthew Woehlke wrote:=20
>>
>> On 2015-06-05 12:01, Nicol Bolas wrote:=20
>> > On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew Woehlke wrote:=
=20
>> >> I think we need expected, but I don't think we should be promoting=20
>> >> it as the One True Method for global error handling. Developers=20
>> >> should continue to use their preferred method for error=20
>> >> propagation. As much as possible, expected should be friendly to=20
>> >> callers that want to turn errors into exceptions.=20
>> >=20
>> > You were doing so well, right up until the last sentence.=20
>>
>> So we should *not* make expected as friendly as possible for callers=20
>> that are going to turn it into an exception?=20
>>
>> > The choice needs to be made by the caller, yes. But the choice should=
=20
>> be=20
>> > made by calling a function that throws exceptions, not by calling some=
=20
>> > member of an `expected`. By then, you've already lost some information=
=20
>> that=20
>> > the function had about the actual error.=20
>>
>> Why? Why does returning an expected necessarily mean that information=20
>> *must* be lost?=20
>>
>> As usual, I think you are missing the point. *If and where* expected can=
=20
>> be used without losing information, is there still a strong motivation=
=20
>> to have a throwing variant?
>
>
> Yes: API consistency.
>
> There will be APIs where exception information can be lost, and there wil=
l=20
> be APIs were information cannot be lost. But that is effectively an=20
> implementation detail, one that should not be visible to the user. The us=
er=20
> shouldn't have to know or care that this particular function throws speci=
al=20
> exceptions.
>
> =20
>> > Oh, you can have `.value()` throw if it doesn't hold a value; that's=
=20
>> fine.=20
>> > But throwing in such a case should not represent the same thing as the=
=20
>> > function actually throwing. It instead represents a caller of the=20
>> > `expected` version who didn't do what he was supposed to do.=20
>>
>> Again, why? My understanding is that it is intended that expected be=20
>> usable by callers that just want exceptions, by simply assuming that the=
=20
>> expected always has a value. Yes, the exact point at which the exception=
=20
>> is thrown is changed (trivially), but I fail to see why that should=20
>> matter.=20
>>
>> Look at it differently. Let's say I have a function:=20
>>
>> expected<T, exception_ptr> foo_expected();=20
>>
> =20
>> Let's further say that the exception is exactly what foo_throws() would=
=20
>> throw, i.e. no information is lost. Why should I then not write:=20
>>
>> T foo_throws() { return foo_expected().value(); }
>>
>
> Because you probably lose elision in this circumstance.
> =20
> I don't understand what you mean. Could develop this?
>
> =20
> And further, if the above is inline, how is it in any way different from=
=20
>> writing at the call site:=20
>>
>> foo().value()
>>
>
> Because:
>
> 1) I don't have to see the syntactically useless `.value()` in my code.
> =20
> If the function return expected you would have the option
>
> await f() ?
>
Yes, because the syntactically useless `await` is much better than the=20
syntactically useless `.value()`. At least .value() isn't *confusing*...
My point is that, whatever syntax you put there is more than the nothing=20
you would use if you called a function that actually threw an exception.
> 2) API consistency. `foo()` throws; `foo_exp()` returns an `expected`.=
=20
> Always (unless _exp doesn't make sense for a particular function).
>
> 3) Why should `foo_exp` return `exception_ptr` at all? Why should it=20
> construct such a heavy-weight object to contain information the majority =
of=20
> which the direct caller of `foo_exp` knows already? Again, going back to=
=20
> Filesystem, the filesyste_error exception contains `path` parameters; why=
=20
> should a Filesystem function that returns `expected` provide access to=20
> parameters that the caller already knows?
>
> 4) `.value()` throws the `bad_expected_access<T>` template class. Which=
=20
> means that's the type the user normally has to catch (when not using=20
> `exception_ptr`). Which means that catching code needs to recognize that=
=20
> the throwing code was using `expected` to do the throwing. Why should it?
> =20
> Why not? future<T> behaves this way. Moving from a function that returns=
=20
> expected<T> to a function that returns future<T> will have not too much=
=20
> consequences on the caller side (if we reach to remove the syntactical=20
> differences - get versus value - or if we provide a monadic interface and=
=20
> both classes are mapped to model this concept).
>
`std::future` throws whatever exception was set into the `promise` it is=20
attached to. The equivalent in `expected` would be `exception_ptr`.
And the consequences of using `exception_ptr` in `expected` are pretty=20
substantial. The code looking at the `expected` can't tell anything useful=
=20
about the nature of the error; all it knows is that some kind of error took=
=20
place.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_315_253876070.1433575471831
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 6, 2015 at 3:08:28 AM UTC-4, Vicente J. =
Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 20:13, Nicol Bolas a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 1:40:33 PM UTC-4,
Matthew Woehlke wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">On
2015-06-05 12:01, Nicol Bolas wrote:
<br>
> On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew
Woehlke wrote:
<br>
>> I think we need expected, but I don't think we should
be promoting
<br>
>> it as the One True Method for global error handling.
Developers
<br>
>> should continue to use their preferred method for
error <br>
>> propagation. As much as possible, expected should be
friendly to
<br>
>> callers that want to turn errors into exceptions.
<br>
> <br>
> You were doing so well, right up until the last sentence.
<br>
<br>
So we should *not* make expected as friendly as possible for
callers
<br>
that are going to turn it into an exception?
<br>
<br>
> The choice needs to be made by the caller, yes. But the
choice should be <br>
> made by calling a function that throws exceptions, not by
calling some <br>
> member of an `expected`. By then, you've already lost
some information that <br>
> the function had about the actual error.
<br>
<br>
Why? Why does returning an expected necessarily mean that
information
<br>
*must* be lost?
<br>
<br>
As usual, I think you are missing the point. *If and where*
expected can
<br>
be used without losing information, is there still a strong
motivation
<br>
to have a throwing variant?</blockquote>
<div><br>
Yes: API consistency.<br>
<br>
There will be APIs where exception information can be lost,
and there will be APIs were information cannot be lost. But
that is effectively an implementation detail, one that should
not be visible to the user. The user shouldn't have to know or
care that this particular function throws special exceptions.<br>
<br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
> Oh, you can have `.value()` throw if it doesn't hold a
value; that's fine. <br>
> But throwing in such a case should not represent the same
thing as the <br>
> function actually throwing. It instead represents a
caller of the <br>
> `expected` version who didn't do what he was supposed to
do.
<br>
<br>
Again, why? My understanding is that it is intended that
expected be
<br>
usable by callers that just want exceptions, by simply
assuming that the
<br>
expected always has a value. Yes, the exact point at which the
exception
<br>
is thrown is changed (trivially), but I fail to see why that
should matter.
<br>
<br>
Look at it differently. Let's say I have a function:
<br>
<br>
expected<T, exception_ptr> foo_expected(); <br>
</blockquote>
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Let's further say that the exception is exactly what
foo_throws() would
<br>
throw, i.e. no information is lost. Why should I then not
write:
<br>
<br>
T foo_throws() { return foo_expected().value(); }<br>
</blockquote>
<div><br>
Because you probably lose elision in this circumstance.<br>
</div>
</div>
</blockquote>
I don't understand what you mean. Could develop this?<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
And further, if the above is inline, how is it in any way
different from
<br>
writing at the call site:
<br>
<br>
foo().value()<br>
</blockquote>
<div><br>
Because:<br>
<br>
1) I don't have to see the syntactically useless `.value()` in
my code.<br>
</div>
</div>
</blockquote>
If the function return expected you would have the option<br>
<br>
await f() ?<br></div></blockquote><div><br>Yes, beca=
use the syntactically useless `await` is much better than the syntactically=
useless `.value()`. At least .value() isn't <i>confusing</i>...<br><br>My =
point is that, whatever syntax you put there is more than the nothing you w=
ould use if you called a function that actually threw an exception.<br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" tex=
t=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
2) API consistency. `foo()` throws; `foo_exp()` returns an
`expected`. Always (unless _exp doesn't make sense for a
particular function).<br>
<br>
3) Why should `foo_exp` return `exception_ptr` at all? Why
should it construct such a heavy-weight object to contain
information the majority of which the direct caller of
`foo_exp` knows already? Again, going back to Filesystem, the
filesyste_error exception contains `path` parameters; why
should a Filesystem function that returns `expected` provide
access to parameters that the caller already knows?<br>
<br>
4) `.value()` throws the `bad_expected_access<T>`
template class. Which means that's the type the user normally
has to catch (when not using `exception_ptr`). Which means
that catching code needs to recognize that the throwing code
was using `expected` to do the throwing. Why should it?<br>
</div>
</div>
</blockquote>
Why not? future<T> behaves this way. Moving from a function
that returns expected<T> to a function that returns
future<T> will have not too much consequences on the caller
side (if we reach to remove the syntactical differences - get versus
value - or if we provide a monadic interface and both classes are
mapped to model this concept).<br></div></blockquote><div><br>`std::fut=
ure` throws whatever exception was set into the `promise` it is attached to=
.. The equivalent in `expected` would be `exception_ptr`.<br><br>And the con=
sequences of using `exception_ptr` in `expected` are pretty substantial. Th=
e code looking at the `expected` can't tell anything useful about the natur=
e of the error; all it knows is that some kind of error took place.<br></di=
v></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_315_253876070.1433575471831--
------=_Part_314_1281707761.1433575471831--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 6 Jun 2015 01:01:10 -0700 (PDT)
Raw View
------=_Part_371_453715643.1433577670620
Content-Type: multipart/alternative;
boundary="----=_Part_372_270957563.1433577670620"
------=_Part_372_270957563.1433577670620
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, June 6, 2015 at 3:02:46 AM UTC-4, Vicente J. Botet Escriba=20
wrote:
>
> Le 03/06/15 07:09, Nicol Bolas a =C3=A9crit :
> =20
>
> However, if an error needs to be propagated, simply inducing `expected` t=
o=20
> throw an exception via `.value()` is... rather useless when needing to=20
> actually report a problem. Oh sure, you can use `error_condition::message=
`=20
> to be told something about why the text didn't parse. But you know=20
> *nothing* about where this happened; that information was lost when the=
=20
> local scope returned the error code. You lose lots of very useful knowled=
ge.
>
> Have you tried to return an expected<T,=20
> your_specific_case_error_with_all_the_needed_information>. What were the=
=20
> problems with this? Performances? With which implementation of expected=
=20
> have you tried? I'm requesting it because mine could be a poor=20
> implementation(it is a POC), and there should be other implementation tha=
t=20
> haven't this performance issue.
>
I'm not sure how you define "performance problem", but returing, as you=20
suggested, `expected<T, unique_ptr<big_giant_object>>` is not something I=
=20
would define to be "fast". Mainly because it requires dynamic memory=20
allocation.
Same goes for using `exception_ptr`. Only there, you have destructively=20
removed the ability for the local scope to actually *know* anything about=
=20
the nature of the error. An `expected<T, exception_ptr>` is only marginally=
=20
better than `optional<T>`, in that it will throw a more appropriate=20
exception.
So not only did you lose a bunch of performance dynamically allocating the=
=20
exception object (let alone its contents like `filesystem::path` and such),=
=20
but you've actually impeded the ability to locally inspect the nature of=20
the error. For the local handler, you'd have genuinely gotten more=20
information using std::error_condition.
> =20
> In that case, you have some local pre-processing of error information,=20
> massaging it into the most useful form for consumption. And this is=20
> starting to resemble the `expected` case, where every layer between the=
=20
> erroring function and the handler must know about these errors and=20
> propagate them explicitly in code. However, this way, you get to use an=
=20
> actual object, rather than having to fit things into an `error_condition`=
..=20
> Yes, `expected` could use any object; however, as previously discussed, i=
f=20
> multiple paths of code need to propagate multiple errors up the same=20
> function, `error_condition` is pretty much the only sane way to go. Unles=
s=20
> you like sorting through `variants`.
> =20
> Are you against variants errors ?
>
Um, yes. Variants are extremely difficult to work with, requiring lots of=
=20
syntax to deal with. You either use a visitor interface to access them,=20
which can check to see if you have all of the possible conditions, but=20
requires massive amounts of syntax (ie: a struct with a bunch of operator()=
=20
overloads. Or you use a large block of `if` statements, which looks better=
=20
(at least its local), but is extremely fragile should the various options=
=20
in the variant change.
> =20
> The exception case is so much cleaner, even with having to do translation=
=20
> at various layers. Only layers that actually do translation need to be=20
> involved in that process; otherwise, the code is clean.
> =20
> Clean is subjective.
>
"Clean" in this case means having no syntax. Whether you think having no=20
syntax is good is another matter.=20
> And then there are things that `expected` flat-out cannot handle or=20
> handles very poorly.
>
> The first is any function that doesn't return a value. Oh yes,=20
> `expected<void, ec>` exists. But it would be rather... foolish to expect=
=20
> everyone to do that. Uniformly.
> =20
> Are you talking of the standard or of an hypothetical user?
>
Users. They drop real return values on the floor all the time.
> =20
> To be fair to `expected`, the latter two can be helped via external tools=
..=20
> It would be possible, particularly with Clang, to write a tool that scans=
=20
> for `expected` return values that are discarded.
> =20
> As we can discard error codes, isn't it?
>
How would a static tool know what an "error code" is? Every library has its=
=20
own type(s) for "error codes". As such, it's hard for a static tool to know=
=20
that any particular type or return value should be considered an error code=
..
Whereas `expected` is a big, neon sign that says, "Test me to check for=20
errors!" It's something that a static tool can actually look for.
=20
> =20
> The more extreme case is object construction, for which the C++ standard=
=20
> has no solution other than exceptions. Options like `expected(in_place_t)=
`=20
> don't really work. You lose "uniform" initialization syntax, as you can't=
=20
> access the initializer_list constructor with {}. It's a nice try, and is=
=20
> necessary for initializing immobile types. But it doesn't work nearly as=
=20
> well as a straight constructor. And most importantly of all, it doesn't=
=20
> actually capture any exceptions thrown by `T`'s constructor.
> =20
> You are right, but error codes doesn't work here neither.=20
>
> expected works better with factories than with constructors that can thro=
w.
>
> struct X {
> static expected<X> makeExpected(...);
> static X make(...); // can throw
> X(...); // can throw
> // ...
> };
>
.... You still "lose 'uniform' initialization syntax". It still "doesn't=20
work nearly as well as a straight constructor". And worst of all, all you=
=20
get from your `expected` is "exception_ptr".
Not very useful for actually figuring out what happened, is it?
> =20
> That all brings me to a number of conclusions:
>
> 1) Exceptions work best in non-local error handling contexts. Local error=
=20
> handling best works via `expected`, except where `expected` cannot be use=
d=20
>
> As for example?
>
Constructors. This is a conclusion; it's based on everything you've read=20
before.
=20
> or is poor at the job.
> =20
> As for example?=20
>
Functions that don't return values or return discardable values. This is a=
=20
conclusion; it's based on everything you've read before.=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_372_270957563.1433577670620
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, June 6, 2015 at 3:02:46 AM UTC-4, Vic=
ente J. Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 03/06/15 07:09, Nicol Bolas a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
However, if an error needs to be propagated, simply inducing
`expected` to throw an exception via `.value()` is... rather
useless when needing to actually report a problem. Oh sure, you
can use `error_condition::message` to be told something about
why the text didn't parse. But you know <i>nothing</i> about
where this happened; that information was lost when the local
scope returned the error code. You lose lots of very useful
knowledge.<br>
<br>
</div>
</blockquote>
Have you tried to return an expected<T,
your_specific_case_error_with_<wbr>all_the_needed_information>. What
were the problems with this? Performances? With which implementation
of expected have you tried? I'm requesting it because mine could be
a poor implementation(it is a POC), and there should be other
implementation that haven't this performance issue.<br></div></blockquo=
te><div><br>I'm not sure how you define "performance problem", but returing=
, as you suggested, `expected<T,
unique_ptr<big_giant_object>>` is not something I would define=
to be "fast". Mainly because it requires dynamic memory allocation.<br><br=
>Same goes for using `exception_ptr`. Only there, you have destructively re=
moved the ability for the local scope to actually <i>know</i> anything abou=
t the nature of the error. An `expected<T, exception_ptr>` is only ma=
rginally better than `optional<T>`, in that it will throw a more appr=
opriate exception.<br><br>So not only did you lose a bunch of performance d=
ynamically allocating the exception object (let alone its contents like `fi=
lesystem::path` and such), but you've actually impeded the ability to local=
ly inspect the nature of the error. For the local handler, you'd have genui=
nely gotten more information using std::error_condition.<br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#00000=
0">
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
In that case, you have some local pre-processing of error
information, massaging it into the most useful form for
consumption. And this is starting to resemble the `expected`
case, where every layer between the erroring function and the
handler must know about these errors and propagate them
explicitly in code. However, this way, you get to use an actual
object, rather than having to fit things into an
`error_condition`. Yes, `expected` could use any object;
however, as previously discussed, if multiple paths of code need
to propagate multiple errors up the same function,
`error_condition` is pretty much the only sane way to go. Unless
you like sorting through `variants`.<br>
</div>
</blockquote>
Are you against variants errors ?<br></div></blockquote><div><br>Um, ye=
s. Variants are extremely difficult to work with, requiring lots of syntax =
to deal with. You either use a visitor interface to access them, which can =
check to see if you have all of the possible conditions, but requires massi=
ve amounts of syntax (ie: a struct with a bunch of operator() overloads. Or=
you use a large block of `if` statements, which looks better (at least its=
local), but is extremely fragile should the various options in the variant=
change.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=
=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
The exception case is so much cleaner, even with having to do
translation at various layers. Only layers that actually do
translation need to be involved in that process; otherwise, the
code is clean.<br>
</div>
</blockquote>
Clean is subjective.<br></div></blockquote><div><br>"Clean" in this cas=
e means having no syntax. Whether you think having no syntax is good is ano=
ther matter. <br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bg=
color=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
And then there are things that `expected` flat-out cannot handle
or handles very poorly.<br>
<br>
The first is any function that doesn't return a value. Oh yes,
`expected<void, ec>` exists. But it would be rather...
foolish to expect everyone to do that. Uniformly.<br>
</div>
</blockquote>
Are you talking of the standard or of an hypothetical user?<br></div></=
blockquote><div><br>Users. They drop real return values on the floor all th=
e time.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=
=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
To be fair to `expected`, the latter two can be helped via
external tools. It would be possible, particularly with Clang,
to write a tool that scans for `expected` return values that are
discarded.<br>
</div>
</blockquote>
As we can discard error codes, isn't it?<br></div></blockquote><div><br=
>How would a static tool know what an "error code" is? Every library has it=
s own type(s) for "error codes". As such, it's hard for a static tool to kn=
ow that any particular type or return value should be considered an error c=
ode.<br><br>Whereas `expected` is a big, neon sign that says, "Test me to c=
heck for errors!" It's something that a static tool can actually look for.<=
br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D=
"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
The more extreme case is object construction, for which the C++
standard has no solution other than exceptions. Options like
`expected(in_place_t)` don't really work. You lose "uniform"
initialization syntax, as you can't access the initializer_list
constructor with {}. It's a nice try, and is necessary for
initializing immobile types. But it doesn't work nearly as well
as a straight constructor. And most importantly of all, it
doesn't actually capture any exceptions thrown by `T`'s
constructor.<br>
</div>
</blockquote>
You are right, but error codes doesn't work here neither. <br>
<br>
expected works better with factories than with constructors that can
throw.<br>
<br>
struct X {<br>
static expected<X> makeExpected(...);<br>
static X make(...); // can throw<br>
X(...); // can throw<br>
// ...<br>
};<br></div></blockquote><div><br>... You still "lose 'uniform'
initialization syntax". It still "doesn't work nearly as well
as a straight constructor". And worst of all, all you get from your=
`expected` is "exception_ptr".<br><br>Not very useful for actually figurin=
g out what happened, is it?<br><br></div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<br>
<blockquote type=3D"cite">
<div dir=3D"ltr"><br>
That all brings me to a number of conclusions:<br>
<br>
1) Exceptions work best in non-local error handling contexts.
Local error handling best works via `expected`, except where
`expected` cannot be used </div>
</blockquote>
As for example?<br></div></blockquote><div><br>Constructors. This is a =
conclusion; it's based on everything you've read before.<br> </div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"=
#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">or is poor at the job.<br>
</div>
</blockquote>
As for example?
</div></blockquote><div><br>Functions that don't return values or retur=
n discardable values. This is a conclusion; it's based on everything you've=
read before. </div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_372_270957563.1433577670620--
------=_Part_371_453715643.1433577670620--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 06 Jun 2015 11:10:04 +0200
Raw View
This is a multi-part message in MIME format.
--------------080505090701090701090200
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 06/06/15 07:40, Nicol Bolas a =C3=A9crit :
> On Friday, June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Botet Escriba=20
> wrote:
>
> Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit :
>> On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigante wrote:
>>
>> C++ is not a functional language, nor is it going to become one
>> in the near future. What happens in "the strongly typed
>> functional programming world" is all well and good... for that
>> world. But that /alone/ doesn't make it good for C++ or any other
>> world.
> Why do you say that C++ is not a functional language? C++ is
> multi-paradigm language, imperative, object oriented, functional, ...
>
>
> To call something a "functional programming language" requires the=20
> inability to break the functional paradigm (admittedly, for varying=20
> degrees of the word "break"). C++ allows you to restrict yourself, to=20
> willingly limit yourself to the functional programming box. What=20
> people think of when they say "functional programming language"=20
> doesn't give you the choice; you live within the box or write in some=20
> other language.
Thanks, this clarify your concern.
>
> That's why C++ is not a functional language. It permits functional=20
> programming, but it doesn't /require/ it.
>
>> You need to justify this with something more than "this is how
>> things work in functional programming monad pattern matching."
> The question is, if expected can be seen as a monad, why don't
> profit from all the experience other languages have had with this
> abstraction.
>
>
> C++ would only be considered to "profit" from this if you see the=20
> addition of functional elements to the language as a priori good. I do=20
> not see the profit in grafting functional elements into C++.
I see that you don't see the benefit.
>
>> We don't have lambda expressions because they're useful "in
>> functional programming"; we have them because it's useful to be
>> able to, quickly and easily, pass stateful functions to various
>> APIs in C++.
> Labmda expressions are useful by them selves. You have the lambda
> calculus. This is the base of the functional programming languages.
>
>
> Yes, they are. But as I said, C++ doesn't have them /for that reason/.=20
> C++ did not add lambda functions to be the basis of a functional=20
> programming model. It added them because they were useful to /many=20
> uses/ of C++, functional or not.
>
Local functions respond clearly to this needs. Do you remember why=20
lambdas were preferred to local functions?
> So you have to provide a reason to do something beyond "that's how=20
> functional programming does it" or "functional languages have=20
> something a lot like that".
I see that moving you from one place to another will not be an easy thing.
>
>> You should not try to turn `expected` into full-frontal
>> "functional programming error handling." Ditch the "monads" and
>> "pattern matching" and so forth; just focus on the basic
>> proposal: a return type that is both error code and value.
> Why?
> When we consider sum types it is normal that we consider pattern
> matching, them are undissociated. expected is a sum type. And also
> a monad. And optional and future and a lot of classes are monads.
> So why not make use the whole set of services that are associated.
>
>
> ... Because C++ is not a functional programming language. It has no=20
> "sum types". It has no "monads". It has no "pattern matching". And it=20
> doesn't need any of those.
Do you change your mind if the language had all these features? Be ready=20
to, then.
>
> Just because C++ has classes that look like certain functional=20
> concepts doesn't mean that C++ ought to treat them the way functional=20
> languages treat them. Like I said before, if you want to argue for=20
> these things, you need to do so on C++'s terms, not on the terms of a=20
> functional language. There must be some benefit to C++ besides,=20
> "that's how functional languages deal with these."
Well, I believe that the current proposals use C++ terms. I believe that=20
we should move to a more concrete discussion about concrete interfaces.
>
>>
>> and that=E2=80=99s what
>> expected would achieve (in contrast to C++03 exception
>> specifications which were handled _at runtime_).
>>
>> The problem with Java checked exceptions is that the syntax
>> simply is not up to the task.
>> Every time you call a function, and you don=E2=80=99t want to
>> propagate the error to your caller,
>> you have to add a try {}catch{} block. This disrupt the
>> control flow: what if you need to do
>> something different depending on the success of the call?
>> instead of a simple branch you have
>>
>> to do one thing immediately after the call and another thing
>> in a _whole other code block_.
>> What if the recovery code is the same among a few calls? you
>> can catch multiple exceptions
>> of the same type in the same catch{} block, but then you
>> cannot discriminate who raised the exception.
>>
>>
>> Note that there are folks in this thread suggesting that
>> something like this be (eventually) allowed:
>>
>> |
>> expected.when{
>> casegood (autovalue){usevalue;}
>> casefailed (autoerror){handle error;}
>> }
>> |
>>
>> That looks an awful lot like a catch block. It seems to "disrupt
>> the control flow" of the program.
> This is just pattern matching. Even if there is not yet a concrete
> proposal for pattern matching, I see it as unavoidable. Of course
> this pattern matching would be adapted to the C++ world.
> There are already a lot of libraries that have a match function.
> Having it on the language makes the language more robust.
>
>
> This "makes the language more robust" only to those who consider the=20
> functional programming model to be the one true way of achieving=20
> robust code.
This gives you an additional degree of freedom.
>
>> It certainly pokes you in the eye a lot.
>>
>> It seems to me that not everyone agrees with you that one is
>> particularly different from the other.
>>
>> Also, with regard to your question of "What if the recovery code
>> is the same among a few calls?", `expected` doesn't exactly solve
>> that one either.
> I don't understand why?
>
>
> Well, those calls would look something like this:
>
> |
> expected<T,error_code>v1 =3Dstuff();
> v1.when{
> casegood (autovalue){usev1;}
> casefailed (autoerror){handle error;}// A
> }
>
> //other processing
>
> expected<T,error_code>v2 =3Dstuff2();
> v2.when{
> casegood (autovalue){usev2;}
> casefailed (autoerror){handle error;} // B
> }
> |
>
> See how both of them use the same "handle error" code? That's what he=20
> was talking about when he said "What if the recovery code is the same=20
> among a few calls?" `expected`,
Ok, I see. There are two cases here, depending on whether the handle=20
error recovers from the error, or just do something and propagates it=20
maybe transformed. I suppose that the handle error in //A recovers from=20
the error and don't returns, otherwise I don't see the need of two error=20
handlers.
I agree that there is no major difference between pattern matching and=20
try_catch blocks.
> even using this `when` syntax, doesn't improve things compared to the=20
> exception case:
>
> |
> try{
> T v1 =3Dstuff();
> usev1;
> }
> catch(error){handle error;}// A
>
> //other processing
>
> try{
> T v2 =3Dstuff2();
> usev2;
> }
> catch(error){handle error;} // B
> |
>
> Indeed, some might even argue that the exception case is easier to=20
> read, since there's no extraneous syntax between the initialization of=20
> the `T` values and their use.
I agree that there is no major difference between pattern matching and=20
try_catch blocks.
One of the missing features of the await proposal is error handling. The=20
Gor's await proposal doesn't provides a specific mechanism to recover=20
from errors. It uses exceptions and try_catch. If I'm not wrong the user=20
needs to call one of the waiting function to throw the exception and=20
then be able to catch it.
|
try{
[] () {// NOISE
T v1 =3Dawait stuff();
usev1;
}().wait(); // NOISE
}
catch(error){handle error;}// A
//other processing
try{
|[] () {// NOISE
|T v2 =3Dawait stuff2();
usev2;
|}().|||wait|(); // NOISE
|}
catch(error){handle error;} // B
|
Gor, please correct me if I'm wrong.
However, I believe that the proposal could be extended so that the NOISE=20
is not needed, and the try-catch block are used to scope the await=20
operator calls.
|
try{
T v1 =3Dawait stuff();
usev1;
}
catch(error){handle error;}// A
//other processing
try{
T v2 =3Dawait stuff2();
usev2;|
|}
catch(error){handle error;} // B
|
>> Note that expected-style error handling also needs good
>> syntax to be effectively used and not
>> incur in the same problems: that=E2=80=99s why I advocate it for=
C++
>> only now that we=E2=80=99ll have the monadic
>> 'do notation' provided by the await 2.0 proposal.
>>
>>
>> What "await 2.0 proposal" are you referring to? What 'do
>> notation'? I don't see anything like this in N4499.
>>
>> Also, something will seriously be wrong in C++ if this becomes
>> legitimate error handling syntax:
>>
>> |
>> autob =3D(await (await a).foo()).bar();
>> |
>>
>> When I look at this, I see syntax that says "stop here until this
>> completes", not syntax that says, "handle errors that are
>> returned by this expression."
> You should read again the resumable functions proposal.
>
>
> /Which/ "resumable functions proposal"? The most recent thing on this=20
> subject that I can find (N4499) is pure standardese; trying to figure=20
> out what the dozens of changes across dozens of chapters actually=20
> means is painful. Even finding out something as simple as what `await`=20
> means when applied to an expression is byzantine.
>
> If you're talking about N4402, well, that was harder to find, since=20
> it's not in the repository=20
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/>. I managed=20
> to find iton isocpp.org <https://isocpp.org/blog/2015/04/n4402>. I=20
> haven't gone through it in any detail, but I haven't seen the part=20
> that said `await` means error handling for `expected`.
I was referring to the previous version. It is normal that expected is=20
not mentioned as it is not part of the standard and a little bit=20
controversial ;-)
I have not read N4402 yet, I will do. If isn't clear in the document how=20
await propagates errors, there is something to be fixed.
>
> Equally importantly, what I was referring to was the use of the=20
> `await` keyword. Which is intended, by both N4402 and N4499, to be=20
> used for some form of delaying of processing, so that a task can be=20
> resolved. Hence my use of the phrase, "when I /look/ at this..."
coroutines and generators don't imply delay of processing. These are=20
IMHO more basic mechanisms. You can build on top of coroutines alternate=20
concurrency once you have an scheduler.
>
> If you have to tell people, "`await` doesn't mean waiting on something=20
> to be finished <http://dictionary.reference.com/browse/await?db=3D*>,"=20
> that's suggests pretty strongly that you're using the wrong tool to=20
> get a job done.
I don't wanted to say that await don't mean "waiting for something to be=20
finished".
await make_expected();
has just this meaning, but also there is also a meaning of propagate the=20
error when the concerned type wraps an error as the type of await f()=20
unwraps the result of f().
IMHO this means that the await keyword tells more than the feature that=20
is provided. I would prefer a different syntax that is more neutral, but=20
I can live for the time being with await.
>
>> But don't hijack a perfectly good coroutine proposal just to
>> graft `expected`-based error handling onto it. Make it a separate
>> construct, rather than some kind of Congressional rider amendment
>> that's attached to a must-pass budget appropriations bill.
>>
>> That's just disingenuous.
> There is no hijacking at all. The features is defined as it is,
> and it allows this kind of usage. I could concede that the
> original proposed feature was not intended to managed these cases,
>
>
> That's an admission of hijacking. If something is intended to do X,=20
> and then you make it do Y, where Y is decidedly unlike X in more or=20
> less every way, you have /hijacked/ that something, turning it into a=20
> backdoor to get Y accomplished. You even admitted this when you said,=20
> "I would prefer another name having less asynchronous connotation." If=20
> you'd prefer a different name, then clearly that something isn't meant=20
> to perform that function.
>
coroutines and generators were there for decades. The original await=20
proposal was a disguised way to make use of coroutines to provide=20
alternate concurrency. Now the bases are more clear and the proposal has=20
even changed its name. Why? because C++ should provide basic mechanism=20
that can be used in multiple contexts. This is the C++ way
> It's things like this that got us our current template metaprogramming=20
> functionality. And while there have been good things that came of it,=20
> it requires such a degree of expert knowledge that only a minority of=20
> C++ programmers can use it. Whereas, if it were a designed feature=20
> rather than an ad-hoc hack, it would have been designed to be more=20
> useable.
>
Not really, what is happening with await and coroutines is different=20
because we are identifying on time the good abstractions.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------080505090701090701090200
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 06/06/15 07:40, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 4:53:15 PM UTC-4,
Vicente J. Botet Escriba wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 8:34:24 AM
UTC-4, Nicola Gigante wrote:<br>
<div><br>
C++ is not a functional language, nor is it going to
become one in the near future. What happens in "the
strongly typed functional programming world" is all
well and good... for that world. But that <i>alone</i>
doesn't make it good for C++ or any other world.<br>
</div>
</div>
</blockquote>
Why do you say that C++ is not a functional language? C++ is
multi-paradigm language, imperative, object oriented,
functional, ...<br>
</div>
</blockquote>
<div><br>
To call something a "functional programming language" requires
the inability to break the functional paradigm (admittedly,
for varying degrees of the word "break"). C++ allows you to
restrict yourself, to willingly limit yourself to the
functional programming box. What people think of when they say
"functional programming language" doesn't give you the choice;
you live within the box or write in some other language.<br>
</div>
</div>
</blockquote>
Thanks, this clarify your concern.<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
That's why C++ is not a functional language. It permits
functional programming, but it doesn't <i>require</i> it.<br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> You need to justify this with something more than
"this is how things work in functional programming
monad pattern matching."<br>
</div>
</div>
</blockquote>
The question is, if expected can be seen as a monad, why
don't profit from all the experience other languages have
had with this abstraction.</div>
</blockquote>
<div><br>
C++ would only be considered to "profit" from this if you see
the addition of functional elements to the language as a
priori good. I do not see the profit in grafting functional
elements into C++.<br>
</div>
</div>
</blockquote>
I see that you don't see the benefit.<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> We don't have lambda expressions because they're
useful "in functional programming"; we have them
because it's useful to be able to, quickly and easily,
pass stateful functions to various APIs in C++. </div>
</div>
</blockquote>
Labmda expressions are useful by them selves. You have the
lambda calculus. This is the base of the functional
programming languages.</div>
</blockquote>
<div><br>
Yes, they are. But as I said, C++ doesn't have them <i>for
that reason</i>. C++ did not add lambda functions to be the
basis of a functional programming model. It added them because
they were useful to <i>many uses</i> of C++, functional or
not.<br>
<br>
</div>
</div>
</blockquote>
Local functions respond clearly to this needs.=C2=A0 Do you remember wh=
y
lambdas=C2=A0 were preferred to local functions?<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>So you have to provide a reason to do something beyond
"that's how functional programming does it" or "functional
languages have something a lot like that".</div>
</div>
</blockquote>
I see that moving you from one place to another will not be an easy
thing.<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> You should not try to turn `expected` into
full-frontal "functional programming error handling."
Ditch the "monads" and "pattern matching" and so
forth; just focus on the basic proposal: a return type
that is both error code and value.<br>
</div>
</div>
</blockquote>
Why?<br>
When we consider sum types it is normal that we consider
pattern matching, them are undissociated. expected is a sum
type. And also a monad. And optional and future and a lot of
classes are monads. So why not make use the whole set of
services that are associated.<br>
</div>
</blockquote>
<div><br>
... Because C++ is not a functional programming language. It
has no "sum types". It has no "monads". It has no "pattern
matching". And it doesn't need any of those.<br>
</div>
</div>
</blockquote>
Do you change your mind if the language had all these features? Be
ready to, then.<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
Just because C++ has classes that look like certain functional
concepts doesn't mean that C++ ought to treat them the way
functional languages treat them. Like I said before, if you
want to argue for these things, you need to do so on C++'s
terms, not on the terms of a functional language. There must
be some benefit to C++ besides, "that's how functional
languages deal with these."<br>
</div>
</div>
</blockquote>
Well, I believe that the current proposals use C++ terms. I believe
that we should move to a more concrete discussion about concrete
interfaces. <br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div style=3D"word-wrap:break-word">
<div>
<div> and that=E2=80=99s what</div>
<div>expected would achieve (in contrast to C++03
exception specifications which were handled _at
runtime_).</div>
<div><br>
</div>
<div>The problem with Java checked exceptions is
that the syntax simply is not up to the task.</div>
<div>Every time you call a function, and you don=E2=
=80=99t
want to propagate the error to your caller,</div>
<div>you have to add a try {}catch{} block. This
disrupt the control flow: what if you need to do</d=
iv>
<div>something different depending on the success
of the call? instead of a simple branch you have</d=
iv>
</div>
</div>
</blockquote>
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div style=3D"word-wrap:break-word">
<div>
<div>to do one thing immediately after the call
and another thing in a _whole other code block_.</d=
iv>
<div>What if the recovery code is the same among a
few calls? you can catch multiple exceptions</div>
<div>of the same type in the same catch{} block,
but then you cannot discriminate who raised the
exception.</div>
</div>
</div>
</blockquote>
<div><br>
Note that there are folks in this thread suggesting
that something like this be (eventually) allowed:<br>
<br>
<div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px;word-wrap:break-word"><code>
<div><span style=3D"color:#000">=C2=A0 expected</span=
><span
style=3D"color:#660">.</span><span
style=3D"color:#008">when</span><span
style=3D"color:#000"> </span><span
style=3D"color:#660">{</span><span
style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">c=
ase</span><span
style=3D"color:#000"> good </span><span
style=3D"color:#660">(</span><span
style=3D"color:#008">auto</span><span
style=3D"color:#000"> value</span><span
style=3D"color:#660">)</span><span
style=3D"color:#000"> </span><span
style=3D"color:#660">{</span><span
style=3D"color:#000"> </span><span
style=3D"color:#008">use</span><span
style=3D"color:#000"> value</span><span
style=3D"color:#660">;</span><span
style=3D"color:#000"> </span><span
style=3D"color:#660">}</span><span
style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">c=
ase</span><span
style=3D"color:#000"> failed </span><span
style=3D"color:#660">(</span><span
style=3D"color:#008">auto</span><span
style=3D"color:#000"> error</span><span
style=3D"color:#660">)</span><span
style=3D"color:#000"> </span><span
style=3D"color:#660">{</span><span
style=3D"color:#000"> handle error</span><span
style=3D"color:#660">;</span><span
style=3D"color:#000"> </span><span
style=3D"color:#660">}</span><span
style=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#660">}</span>=
</div>
</code></div>
<div><br>
</div>
That looks an awful lot like a catch block. It seems
to "disrupt the control flow" of the program.<br>
</div>
</div>
</blockquote>
This is just pattern matching. Even if there is not yet a
concrete proposal for pattern matching, I see it as
unavoidable. Of course this pattern matching would be
adapted to the C++ world.<br>
There are already a lot of libraries that have a match
function. Having it on the language makes the language more
robust.<br>
</div>
</blockquote>
<div><br>
This "makes the language more robust" only to those who
consider the functional programming model to be the one true
way of achieving robust code.<br>
</div>
</div>
</blockquote>
This gives you an additional degree of freedom. <br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> It certainly pokes you in the eye a lot.<br>
<br>
It seems to me that not everyone agrees with you that
one is particularly different from the other.<br>
<br>
Also, with regard to your question of "What if the
recovery code is the same among a few calls?",
`expected` doesn't exactly solve that one either. </div>
</div>
</blockquote>
I don't understand why?<br>
</div>
</blockquote>
<div><br>
Well, those calls would look something like this:<br>
<br>
<div class=3D"prettyprint" style=3D"background-color: rgb(250,
250, 250); border-color: rgb(187, 187, 187); border-style:
solid; border-width: 1px; word-wrap: break-word;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #000;"
class=3D"styled-by-prettify">expected</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span
style=3D"color: #000;" class=3D"styled-by-prettify">T</sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">
error_code</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">></span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v1 <=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> stuf=
f</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
v1</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">.</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">when</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">case</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> good
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">auto</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> valu=
e</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">use</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v1</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">case</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
failed </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">auto</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> erro=
r</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">
handle error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"> </span><span
style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> // A=
<br>
=C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">}</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"><br>
<br>
</span><span style=3D"color: #800;"
class=3D"styled-by-prettify">//other processing</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
<br>
expected</span><span style=3D"color: #660;"
class=3D"styled-by-prettify"><</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">T</sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">
error_code</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">></span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v2 <=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
stuff2</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">();</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
v2</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">.</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">when</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">case</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> good
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">auto</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> valu=
e</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">use</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v2</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 </span><span style=3D"color: #008;"
class=3D"styled-by-prettify">case</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
failed </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">auto</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> erro=
r</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">
handle error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"> </span><span
style=3D"color: #660;" class=3D"styled-by-prettify">} // =
B</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">}</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"><br>
</span></div>
</code></div>
<br>
See how both of them use the same "handle error" code? That's
what he was talking about when he said "What if the recovery
code is the same among a few calls?" `expected`, </div>
</div>
</blockquote>
<br>
Ok, I see. There are two cases here, depending on whether the handle
error recovers from the error, or just do something and propagates
it maybe transformed. I suppose that the handle error in //A
recovers from the error and don't returns, otherwise I don't see the
need of two error handlers.<br>
I agree that there is no major difference between pattern matching
and try_catch blocks.<br>
<br>
<br>
<br>
<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>even using this `when` syntax, doesn't improve things
compared to the exception case:<br>
<br>
<div class=3D"prettyprint" style=3D"background-color: rgb(250,
250, 250); border-color: rgb(187, 187, 187); border-style:
solid; border-width: 1px; word-wrap: break-word;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #008;"
class=3D"styled-by-prettify">try</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
T v1 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or:
#000;" class=3D"styled-by-prettify"> stuff</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">use</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v1</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">}</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">catch</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">error=
</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">){</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">
handle error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;}</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> // A=
<br>
<br>
</span><span style=3D"color: #800;"
class=3D"styled-by-prettify">//other processing</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
<br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">try</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
T v2 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or:
#000;" class=3D"styled-by-prettify"> stuff2</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">use</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v2</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">}</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">catch</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">error=
</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">){</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">
handle error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;} // B</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span></div>
</code></div>
<br>
Indeed, some might even argue that the exception case is
easier to read, since there's no extraneous syntax between the
initialization of the `T` values and their use.<br>
</div>
</div>
</blockquote>
I agree that there is no major difference between pattern matching
and try_catch blocks.<br>
<br>
One of the missing features of the await proposal is error handling.
The Gor's await proposal doesn't provides a specific mechanism to
recover from errors. It uses exceptions and try_catch. If I'm not
wrong the user needs to call one of the waiting function to throw
the exception and then be able to catch it. <br>
<br>
<div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
250); border-color: rgb(187, 187, 187); border-style: solid;
border-width: 1px; word-wrap: break-word;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #008;"
class=3D"styled-by-prettify">try</span><span style=3D"color:
#660;" class=3D"styled-by-prettify">{</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
[] () {// NOISE<br>
T v1 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">=3D</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"> await stuff</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
use</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v1</span><=
span
style=3D"color: #660;" class=3D"styled-by-prettify">;<br>
}().wait(); // NOISE<br>
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">}</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
catch</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify">error</span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify">){</span><s=
pan
style=3D"color: #000;" class=3D"styled-by-prettify"> handle
error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;}</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"> // A<br>
<br>
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">=
//other
processing</span><span style=3D"color: #000;"
class=3D"styled-by-prettify"><br>
<br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
try</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<code
class=3D"prettyprint"><span style=3D"color: #000;"
class=3D"styled-by-prettify">[] () {// NOISE<br>
</span></code>T v2 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">=3D</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"> await stuff2</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
use</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v2</span><=
span
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
<code
class=3D"prettyprint"><span style=3D"color: #660;"
class=3D"styled-by-prettify">}().</span></code></span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><code
class=3D"prettyprint"><span style=3D"color: #660;"
class=3D"styled-by-prettify"><code class=3D"prettyprint"><s=
pan
style=3D"color: #660;" class=3D"styled-by-prettify">wai=
t</span></code>();
// NOISE<br>
</span><span style=3D"color: #000;"
class=3D"styled-by-prettify"></span><span style=3D"color:
#660;" class=3D"styled-by-prettify"></span></code>}</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
catch</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify">error</span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify">){</span><s=
pan
style=3D"color: #000;" class=3D"styled-by-prettify"> handle
error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;} // B</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"><br>
</span></div>
</code></div>
<br>
<br>
Gor, please correct me if I'm wrong.<br>
<br>
However, I believe that the proposal could be extended so that the
NOISE is not needed, and the try-catch block are used to scope the
await operator calls.<br>
<br>
<br>
<div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,
250); border-color: rgb(187, 187, 187); border-style: solid;
border-width: 1px; word-wrap: break-word;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #008;"
class=3D"styled-by-prettify">try</span><span style=3D"color:
#660;" class=3D"styled-by-prettify">{</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
T v1 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">=3D</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"> await stuff</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
use</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v1</span><=
span
style=3D"color: #660;" class=3D"styled-by-prettify">;<br>
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
}</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
catch</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify">error</span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify">){</span><s=
pan
style=3D"color: #000;" class=3D"styled-by-prettify"> handle
error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;}</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"> // A<br>
<br>
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">=
//other
processing</span><span style=3D"color: #000;"
class=3D"styled-by-prettify"><br>
<br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
try</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
T
v2 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">=3D</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"> await stuff2</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">();</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
use</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> v2</span><=
span
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"></span><spa=
n
style=3D"color: #660;" class=3D"styled-by-prettify"><code
class=3D"prettyprint"><span style=3D"color: #660;"
class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #000;"
class=3D"styled-by-prettify"></span><span style=3D"color:
#660;" class=3D"styled-by-prettify"></span></code>}</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
catch</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify">error</span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify">){</span><s=
pan
style=3D"color: #000;" class=3D"styled-by-prettify"> handle
error</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">;} // B</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"><br>
</span></div>
</code></div>
<br>
<br>
<br>
=C2=A0<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> </div>
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div style=3D"word-wrap:break-word">
<div>
<div>Note that expected-style error handling also
needs good syntax to be effectively used and not</d=
iv>
<div>incur in the same problems: that=E2=80=99s why I
advocate it for C++ only now that we=E2=80=99ll hav=
e the
monadic</div>
<div>'do notation' provided by the await 2.0
proposal.</div>
</div>
</div>
</blockquote>
<div><br>
What "await 2.0 proposal" are you referring to? What
'do notation'? I don't see anything like this in
N4499.<br>
<br>
Also, something will seriously be wrong in C++ if this
becomes legitimate error handling syntax:<br>
<br>
<div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px;word-wrap:break-word"><code>
<div><span style=3D"color:#008">auto</span><span
style=3D"color:#000"> b </span><span
style=3D"color:#660">=3D</span><span
style=3D"color:#000"> </span><span
style=3D"color:#660">(</span><span
style=3D"color:#000">await </span><span
style=3D"color:#660">(</span><span
style=3D"color:#000">await a</span><span
style=3D"color:#660">).</span><span
style=3D"color:#000">foo</span><span
style=3D"color:#660">()).</span><span
style=3D"color:#000">bar</span><span
style=3D"color:#660">();</span></div>
</code></div>
<br>
When I look at this, I see syntax that says "stop here
until this completes", not syntax that says, "handle
errors that are returned by this expression." </div>
</div>
</blockquote>
You should read again the resumable functions proposal.</div>
</blockquote>
<div><br>
<i>Which</i> "resumable functions proposal"? The most recent
thing on this subject that I can find (N4499) is pure
standardese; trying to figure out what the dozens of changes
across dozens of chapters actually means is painful. Even
finding out something as simple as what `await` means when
applied to an expression is byzantine.<br>
<br>
If you're talking about N4402, well, that was harder to find,
since it's not in <a moz-do-not-send=3D"true"
href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015=
/">the
repository</a>. I managed to find it<a
moz-do-not-send=3D"true"
href=3D"https://isocpp.org/blog/2015/04/n4402"> on isocpp.org</=
a>.
I haven't gone through it in any detail, but I haven't seen
the part that said `await` means error handling for
`expected`.<br>
</div>
</div>
</blockquote>
I was referring to the previous version. It is normal that expected
is not mentioned as it is not part of the standard and a little bit
controversial ;-)<br>
I have not read N4402 yet, I will do. If isn't clear in the document
how await propagates errors, there is something to be fixed.<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
Equally importantly, what I was referring to was the use of
the `await` keyword. Which is intended, by both N4402 and
N4499, to be used for some form of delaying of processing, so
that a task can be resolved. Hence my use of the phrase, "when
I <i>look</i> at this..."<br>
</div>
</div>
</blockquote>
coroutines and generators don't imply delay of processing. These are
IMHO more basic mechanisms. You can build on top of coroutines
alternate concurrency once you have an scheduler.<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
If you have to tell people, "`await` doesn't mean <a
moz-do-not-send=3D"true"
href=3D"http://dictionary.reference.com/browse/await?db=3D*">wa=
iting
on something to be finished</a>," that's suggests pretty
strongly that you're using the wrong tool to get a job done.<br>
</div>
</div>
</blockquote>
I don't wanted to say that await don't mean "waiting for something
to be finished". <br>
<br>
=C2=A0=C2=A0=C2=A0 await make_expected();<br>
<br>
has just this meaning, but also there is also a meaning of propagate
the error when the concerned type wraps an error as the type of
await f() unwraps the result of f().<br>
<br>
IMHO this means that the await keyword tells more than the feature
that is provided. I would prefer a different syntax that is more
neutral, but I can live for the time being with await.<br>
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>But don't hijack a perfectly good coroutine
proposal just to graft `expected`-based error handling
onto it. Make it a separate construct, rather than
some kind of Congressional rider amendment that's
attached to a must-pass budget appropriations bill.<br>
<br>
That's just disingenuous.<br>
</div>
</div>
</blockquote>
There is no hijacking at all. The features is defined as it
is, and it allows this kind of usage. I could concede that
the original proposed feature was not intended to managed
these cases,</div>
</blockquote>
<div><br>
That's an admission of hijacking. If something is intended to
do X, and then you make it do Y, where Y is decidedly unlike X
in more or less every way, you have <i>hijacked</i> that
something, turning it into a backdoor to get Y accomplished.
You even admitted this when you said, "I would prefer another
name having less asynchronous connotation." If you'd prefer a
different name, then clearly that something isn't meant to
perform that function.<br>
<br>
</div>
</div>
</blockquote>
coroutines and generators were there for decades. The original await
proposal was a disguised way to make use of coroutines to provide
alternate concurrency. Now the bases are more clear and the proposal
has even changed its name. Why? because C++ should provide basic
mechanism that can be used in multiple contexts. This is the C++ way
<blockquote
cite=3D"mid:73f53762-0bb8-4dd6-b273-0d2ee710dfb7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>It's things like this that got us our current template
metaprogramming functionality. And while there have been good
things that came of it, it requires such a degree of expert
knowledge that only a minority of C++ programmers can use it.
Whereas, if it were a designed feature rather than an ad-hoc
hack, it would have been designed to be more useable.<br>
</div>
</div>
<br>
</blockquote>
Not really, what is happening with await and coroutines is different
because we are identifying on time the good abstractions.<br>
<br>
Vicente <br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------080505090701090701090200--
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Sat, 6 Jun 2015 02:16:05 -0700 (PDT)
Raw View
------=_Part_394_1255564137.1433582165981
Content-Type: multipart/alternative;
boundary="----=_Part_395_1092135137.1433582165981"
------=_Part_395_1092135137.1433582165981
Content-Type: text/plain; charset=UTF-8
On Saturday, June 6, 2015 at 12:24:31 AM UTC-7, Nicol Bolas wrote:
>
>
> My point is that, whatever syntax you put there is more than the nothing
> you would use if you called a function that actually threw an exception.
>
My point is that such syntactical requirement is a highly desirable feature.
Code that doesn't acknowledge that an expression can utterly subvert the
code flow with no local indication that this might happen is a massive
design flaw.
Code that doesn't acknowledge that it's ignoring a meaningful return value
is a massive design flaw. No, the stuff I presented doesn't solve that
entirely, and clearly wasn't a perfect proposal.
expected<> as it stands today solves a few problems, but absolutely by no
means does it solve all of them, or even the most important ones. If one
takes exceptions as a feature worth avoiding (which some large industries
do, even if you do not) then an expected<> that can still easily end up
throwing exceptions or having UB is rather insufficient. All expected will
have done is give std::pair<Value, Error> a slightly better semantic name.
Functions that use it will be slightly more ergonomic than just "returning"
the value/error in an out parameter. It's more consistent and better for
the stdlib but ultimately it won't have solved any real problems.
Of course, expected<> is modeled off of existing practice found in many
large C++ codebases. Which have arisen due to the need to solve the same
kinds of problems the functional language guys had identified and tackled.
The approach mentioned in previous posts were not brought up "because
functional languages do it." They're because the options presented for C++
thus far are all inadequate for a significant portion of the primary
"customers" of the language. And that's frustrating because we _know_ it
can be better (if not perfect) as we have clear examples of better ways of
doing things. All one must do is look over at those dirty
functional-programmer hippies and pay attention for a few of them (hey,
many of them have exceptions _too_; turns out they're not all that
different from us!).
There is a very huge difference between it being merely a possibility to
write code that dodges landmines rather than being strongly guided towards
writing code that is obvious, clear, and does exactly what it says upon
cursory inspection.
Return codes make incidental mistakes (even for experienced experts) easier
than writing robust code. Exceptions make incidental screwups (even for
experienced experts) easier than writing robust code. BOTH methods result
in degraded productivity, poor user experiences, and lost profits.
That damage can't be undone, but we can stop willfully inflicting more of
it out of our own stubborn refusal to admit that C++ today is not the best
language, nor even the best C++.
Now, certainly, the things I previously mentioned don't solve all problems.
I don't claim to be a genius with a perfect solution for every problem. I
was at least hoping to tap into the minds of other smart people who might
be willing to work through those problems and potential solutions. Not what
I'm going to get, apparently.
We know - and have ample proof - that there are more options for handling
errors than just either return values or exceptions. Yet that's what every
discussion about error handling in C++ turns into: a choice between bad or
suboptimal.
That dichotomous discussion is tiring and unfruitful.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_395_1092135137.1433582165981
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 6, 2015 at 12:24:31 AM UTC-7, Nicol Bola=
s wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
<br>My point is that, whatever syntax you put there is more than the nothin=
g you would use if you called a function that actually threw an exception.<=
br></div></div></blockquote><div><br></div><div>My point is that such synta=
ctical requirement is a highly desirable feature.</div><div><br></div><div>=
Code that doesn't acknowledge that an expression can utterly subvert the co=
de flow with no local indication that this might happen is a massive design=
flaw.</div><div><br></div><div>Code that doesn't acknowledge that it's ign=
oring a meaningful return value is a massive design flaw. No, the stuff I p=
resented doesn't solve that entirely, and clearly wasn't a perfect proposal=
..</div><div><br></div><div>expected<> as it stands today solves a few=
problems, but absolutely by no means does it solve all of them, or even th=
e most important ones. If one takes exceptions as a feature worth avoiding =
(which some large industries do, even if you do not) then an expected<&g=
t; that can still easily end up throwing exceptions or having UB is rather =
insufficient. All expected will have done is give std::pair<Value, Error=
> a slightly better semantic name. Functions that use it will be slightl=
y more ergonomic than just "returning" the value/error in an out parameter.=
It's more consistent and better for the stdlib but ultimately it won't hav=
e solved any real problems.<br></div><div><br></div><div>Of course, expecte=
d<> is modeled off of existing practice found in many large C++ codeb=
ases. Which have arisen due to the need to solve the same kinds of problems=
the functional language guys had identified and tackled.</div><div><br></d=
iv><div>The approach mentioned in previous posts were not brought up "becau=
se functional languages do it." They're because the options presented for C=
++ thus far are all inadequate for a significant portion of the primary "cu=
stomers" of the language. And that's frustrating because we _know_ it can b=
e better (if not perfect) as we have clear examples of better ways of doing=
things. All one must do is look over at those dirty functional-programmer =
hippies and pay attention for a few of them (hey, many of them have excepti=
ons _too_; turns out they're not all that different from us!).</div><div><b=
r></div><div>There is a very huge difference between it being merely a poss=
ibility to write code that dodges landmines rather than being strongly guid=
ed towards writing code that is obvious, clear, and does exactly what it sa=
ys upon cursory inspection.</div><div><br></div><div>Return codes make inci=
dental mistakes (even for experienced experts) easier than writing robust c=
ode. Exceptions make incidental screwups (even for experienced experts) eas=
ier than writing robust code. BOTH methods result in degraded productivity,=
poor user experiences, and lost profits.</div><div><br></div><div>That dam=
age can't be undone, but we can stop willfully inflicting more of it out of=
our own stubborn refusal to admit that C++ today is not the best language,=
nor even the best C++.</div><div><br></div><div>Now, certainly, the things=
I previously mentioned don't solve all problems. I don't claim to be a gen=
ius with a perfect solution for every problem. I was at least hoping to tap=
into the minds of other smart people who might be willing to work through =
those problems and potential solutions. Not what I'm going to get, apparent=
ly.</div><div><br></div><div>We know - and have ample proof - that there ar=
e more options for handling errors than just either return values or except=
ions. Yet that's what every discussion about error handling in C++ turns in=
to: a choice between bad or suboptimal.</div><div><br></div><div>That dicho=
tomous discussion is tiring and unfruitful.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_395_1092135137.1433582165981--
------=_Part_394_1255564137.1433582165981--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 06 Jun 2015 13:00:00 +0200
Raw View
This is a multi-part message in MIME format.
--------------050500050804010505090508
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 06/06/15 09:19, Nicol Bolas a =C3=A9crit :
> On Friday, June 5, 2015 at 6:42:30 PM UTC-4, Matthew Woehlke wrote:
>
> On 2015-06-05 17:34, Vicente J. Botet Escriba wrote:
> > Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
> >> OK, so... what about static analysis tools? We already have great
> >> static tools that can detect the use of many uninitialized values.
> >
> > expected as optional, and I hope would variant, are never
> uninitialized
> > as these classes have default constructor.
>
> Not the expected/optional itself, but the contained value.
>
> IOW, this is a (potential) error:
>
> auto x =3D function_that_returns_expected_or_optional;
> do_something(x.value());
>
> ...because you didn't check that 'x' actually *has* a value, and thus
> value() might throw.
>
> Nicol is of the opinion that one should never write code like
> this, even
> if throwing from the context where value() is called if there is no
> value is the intended behavior.
>
> I have to ask, though: in that case, why throw at all?
>
>
> Because "wrong" doesn't necessarily mean "shouldn't be allowed."
>
> Sometimes, some piece of code winds up with an `expected` that doesn't=20
> have its value, and that code's precondition is that it should have a=20
> value. The code doesn't check it because it shouldn't be possible, but=20
> maybe they've done something that defeats the static analysis tool (or=20
> their compiler isn't smart enough to find it for them). But for=20
> whatever reason, this code bug has happened.
>
if there is a precondition that there is a value, the function should=20
take a T as parameter not an expected<T>.
> If that happens, the application should terminate, but in a way that=20
> can be traced back at least to the point where `value` was called.=20
> Throwing an uncaught exception is a reasonable way to do that.
>
> Really, I envision expected as a 'delayed throw' mechanism. The
> point is
> to return an expected instead of throwing immediately, and instead
> delay
> *the throw that otherwise would have happened* until the user calls
> value(), thus giving a window where the user can choose to handle the
> error before an exception is thrown.
>
>
> Well, a lot of the functional programming crowd in this thread seems=20
> to think that `expected` objects should be flying up the call-stack=20
> via `await` shenanigans or whatever. So there's some disagreement here=20
> as to how `expected` ought to be used.
>
Why you want to tell to the user how it must use expected? This is not=20
up to the standard.
> I see `expected` as how I described it in my look at it: an alternate=20
> way to pass an error directly to the local calling scope.
>
> There are several problems with thinking of `expected` as merely a=20
> delayed throwing mechanic. Part of it has to do with what goes into=20
> the error code portion.
>
> As previously stated, exceptions often need rich information, since=20
> they are usually processed far from their invocation site. `expected`=20
> objects are usually processed close enough that the local code can get=20
> much of this information themselves. In those cases, a simple=20
> std::error_condition is often sufficient.
>
> Something like `exception_ptr` is completely opaque; the only thing=20
> you can do with that is throw it. You can't inspect it to find out=20
> which exception was captured or anything. Even a shared pointer to=20
> some object is problematic because you're having to allocate memory=20
> just to pass an error.
std::variant is an valid alternative. It is equivalent to exception=20
specifications. I prefer yet std::any that as the ABI don't changes when=20
new errors are added. Neither of them forces an allocation.
the proposed expected is open and let the developer choose the error=20
mechanism that is the more appropriated to its application. The C++=20
standard library could choose it on a case by case. If we need to let=20
the user choose the mechanism we need to add it as parameter as I=20
suggested with the template parameter ErrorMechanism.
>
> Because of all of that, exceptions thrown by `.value` exceptions will=20
> oftentimes be of limited use compared to exceptions that would=20
> natively be thrown. Couple that with the static analysis issues, and=20
> you have a pretty good argument for good coding practices to suggest=20
> avoiding the capture of any exception thrown by `.value()`.
Well, we just disagree on how the user could or should use expected.=20
This is not a problem for the standard.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------050500050804010505090508
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 06/06/15 09:19, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:b762ad82-04ea-4d5c-a33f-f7f0412833ba@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 6:42:30 PM UTC-4,
Matthew Woehlke wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On
2015-06-05 17:34, Vicente J. Botet Escriba wrote:
<br>
> Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
<br>
>> OK, so... what about static analysis tools? We
already have great
<br>
>> static tools that can detect the use of many
uninitialized values.
<br>
>
<br>
> expected as optional, and I hope would variant, are never
uninitialized
<br>
> as these classes have default constructor.
<br>
<br>
Not the expected/optional itself, but the contained value.
<br>
<br>
IOW, this is a (potential) error:
<br>
<br>
=C2=A0 auto x =3D function_that_returns_<wbr>expected_or_optional=
;
<br>
=C2=A0 do_something(x.value());
<br>
<br>
...because you didn't check that 'x' actually *has* a value,
and thus
<br>
value() might throw.
<br>
<br>
Nicol is of the opinion that one should never write code like
this, even
<br>
if throwing from the context where value() is called if there
is no
<br>
value is the intended behavior.
<br>
<br>
I have to ask, though: in that case, why throw at all?<br>
</blockquote>
<div><br>
Because "wrong" doesn't necessarily mean "shouldn't be
allowed."<br>
<br>
Sometimes, some piece of code winds up with an `expected` that
doesn't have its value, and that code's precondition is that
it should have a value. The code doesn't check it because it
shouldn't be possible, but maybe they've done something that
defeats the static analysis tool (or their compiler isn't
smart enough to find it for them). But for whatever reason,
this code bug has happened.<br>
<br>
</div>
</div>
</blockquote>
if there is a precondition that there is a value, the function
should take a T as parameter not an expected<T>.<br>
<blockquote
cite=3D"mid:b762ad82-04ea-4d5c-a33f-f7f0412833ba@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>If that happens, the application should terminate, but in a
way that can be traced back at least to the point where
`value` was called. Throwing an uncaught exception is a
reasonable way to do that.<br>
<br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
Really, I envision expected as a 'delayed throw' mechanism.
The point is
<br>
to return an expected instead of throwing immediately, and
instead delay
<br>
*the throw that otherwise would have happened* until the user
calls
<br>
value(), thus giving a window where the user can choose to
handle the
<br>
error before an exception is thrown.<br>
</blockquote>
<div><br>
Well, a lot of the functional programming crowd in this thread
seems to think that `expected` objects should be flying up the
call-stack via `await` shenanigans or whatever. So there's
some disagreement here as to how `expected` ought to be used.<br>
<br>
</div>
</div>
</blockquote>
Why you want to tell to the user how it must use expected? This is
not up to the standard.<br>
<blockquote
cite=3D"mid:b762ad82-04ea-4d5c-a33f-f7f0412833ba@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>I see `expected` as how I described it in my look at it: an
alternate way to pass an error directly to the local calling
scope.<br>
<br>
There are several problems with thinking of `expected` as
merely a delayed throwing mechanic. Part of it has to do with
what goes into the error code portion.<br>
<br>
As previously stated, exceptions often need rich information,
since they are usually processed far from their invocation
site. `expected` objects are usually processed close enough
that the local code can get much of this information
themselves. In those cases, a simple std::error_condition is
often sufficient.<br>
<br>
Something like `exception_ptr` is completely opaque; the only
thing you can do with that is throw it. You can't inspect it
to find out which exception was captured or anything. Even a
shared pointer to some object is problematic because you're
having to allocate memory just to pass an error.<br>
</div>
</div>
</blockquote>
std::variant is an valid alternative. It is equivalent to exception
specifications. I prefer yet std::any that as the ABI don't changes
when new errors are added. Neither of them forces an allocation.<br>
<br>
the proposed expected is open and let the developer choose the error
mechanism that is the more appropriated to its application. The C++
standard library could choose it on a case by case. If we need to
let the user choose the mechanism we need to add it as parameter as
I suggested with the template parameter ErrorMechanism.=C2=A0 <br>
<blockquote
cite=3D"mid:b762ad82-04ea-4d5c-a33f-f7f0412833ba@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
Because of all of that, exceptions thrown by `.value`
exceptions will oftentimes be of limited use compared to
exceptions that would natively be thrown. Couple that with the
static analysis issues, and you have a pretty good argument
for good coding practices to suggest avoiding the capture of
any exception thrown by `.value()`.<br>
</div>
</div>
</blockquote>
Well, we just disagree on how the user could or should use expected.
This is not a problem for the standard.<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------050500050804010505090508--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 06 Jun 2015 13:04:00 +0200
Raw View
This is a multi-part message in MIME format.
--------------050903060009010200090408
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 06/06/15 09:24, Nicol Bolas a =C3=A9crit :
> On Saturday, June 6, 2015 at 3:08:28 AM UTC-4, Vicente J. Botet=20
> Escriba wrote:
>
> Le 05/06/15 20:13, Nicol Bolas a =C3=A9crit :
>> On Friday, June 5, 2015 at 1:40:33 PM UTC-4, Matthew Woehlke wrote:
>>
>> On 2015-06-05 12:01, Nicol Bolas wrote:
>> > On Thursday, June 4, 2015 at 11:05:07 AM UTC-4, Matthew
>> Woehlke wrote:
>>
>> Again, why? My understanding is that it is intended that
>> expected be
>> usable by callers that just want exceptions, by simply
>> assuming that the
>> expected always has a value. Yes, the exact point at which
>> the exception
>> is thrown is changed (trivially), but I fail to see why that
>> should matter.
>>
>> Look at it differently. Let's say I have a function:
>>
>> expected<T, exception_ptr> foo_expected();
>>
>>
>> Let's further say that the exception is exactly what
>> foo_throws() would
>> throw, i.e. no information is lost. Why should I then not write:
>>
>> T foo_throws() { return foo_expected().value(); }
>>
>>
>> Because you probably lose elision in this circumstance.
> I don't understand what you mean. Could develop this?
>>
>> And further, if the above is inline, how is it in any way
>> different from
>> writing at the call site:
>>
>> foo().value()
>>
>>
>> Because:
>>
>> 1) I don't have to see the syntactically useless `.value()` in my
>> code.
> If the function return expected you would have the option
>
> await f() ?
>
>
> Yes, because the syntactically useless `await` is much better than the=20
> syntactically useless `.value()`. At least .value() isn't /confusing/...
Each one has a different meaning :)
>
> My point is that, whatever syntax you put there is more than the=20
> nothing you would use if you called a function that actually threw an=20
> exception.
>
>> 2) API consistency. `foo()` throws; `foo_exp()` returns an
>> `expected`. Always (unless _exp doesn't make sense for a
>> particular function).
>>
>> 3) Why should `foo_exp` return `exception_ptr` at all? Why should
>> it construct such a heavy-weight object to contain information
>> the majority of which the direct caller of `foo_exp` knows
>> already? Again, going back to Filesystem, the filesyste_error
>> exception contains `path` parameters; why should a Filesystem
>> function that returns `expected` provide access to parameters
>> that the caller already knows?
>>
>> 4) `.value()` throws the `bad_expected_access<T>` template class.
>> Which means that's the type the user normally has to catch (when
>> not using `exception_ptr`). Which means that catching code needs
>> to recognize that the throwing code was using `expected` to do
>> the throwing. Why should it?
> Why not? future<T> behaves this way. Moving from a function that
> returns expected<T> to a function that returns future<T> will have
> not too much consequences on the caller side (if we reach to
> remove the syntactical differences - get versus value - or if we
> provide a monadic interface and both classes are mapped to model
> this concept).
>
>
> `std::future` throws whatever exception was set into the `promise` it=20
> is attached to. The equivalent in `expected` would be `exception_ptr`.
>
> And the consequences of using `exception_ptr` in `expected` are pretty=20
> substantial. The code looking at the `expected` can't tell anything=20
> useful about the nature of the error; all it knows is that some kind=20
> of error took place.
>
Why?
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------050903060009010200090408
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 06/06/15 09:24, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:0243bdcb-c0a1-4343-88d6-caef3e962cbb@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Saturday, June 6, 2015 at 3:08:28 AM UTC-4,
Vicente J. Botet Escriba wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 20:13, Nicol Bolas a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 1:40:33 PM
UTC-4, Matthew Woehlke wrote:
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">On 2015-06-05 12:01, Nicol
Bolas wrote: <br>
> On Thursday, June 4, 2015 at 11:05:07 AM UTC-4,
Matthew Woehlke wrote: <br>
<br>
Again, why? My understanding is that it is intended
that expected be <br>
usable by callers that just want exceptions, by simply
assuming that the <br>
expected always has a value. Yes, the exact point at
which the exception <br>
is thrown is changed (trivially), but I fail to see
why that should matter. <br>
<br>
Look at it differently. Let's say I have a function: <br>
<br>
=C2=A0 expected<T, exception_ptr> foo_expected(); <=
br>
</blockquote>
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex"> <br>
Let's further say that the exception is exactly what
foo_throws() would <br>
throw, i.e. no information is lost. Why should I then
not write: <br>
<br>
=C2=A0 T foo_throws() { return foo_expected().value(); }<=
br>
</blockquote>
<div><br>
Because you probably lose elision in this
circumstance.<br>
</div>
</div>
</blockquote>
I don't understand what you mean. Could develop this?<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex"> And further, if the above is
inline, how is it in any way different from <br>
writing at the call site: <br>
<br>
=C2=A0 foo().value()<br>
</blockquote>
<div><br>
Because:<br>
<br>
1) I don't have to see the syntactically useless
`.value()` in my code.<br>
</div>
</div>
</blockquote>
If the function return expected you would have the option<br>
<br>
=C2=A0=C2=A0=C2=A0 await f() ?<br>
</div>
</blockquote>
<div><br>
Yes, because the syntactically useless `await` is much better
than the syntactically useless `.value()`. At least .value()
isn't <i>confusing</i>...<br>
</div>
</div>
</blockquote>
Each one has a different meaning :)<br>
<blockquote
cite=3D"mid:0243bdcb-c0a1-4343-88d6-caef3e962cbb@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
My point is that, whatever syntax you put there is more than
the nothing you would use if you called a function that
actually threw an exception.<br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> 2) API consistency. `foo()` throws; `foo_exp()`
returns an `expected`. Always (unless _exp doesn't
make sense for a particular function).<br>
<br>
3) Why should `foo_exp` return `exception_ptr` at all?
Why should it construct such a heavy-weight object to
contain information the majority of which the direct
caller of `foo_exp` knows already? Again, going back
to Filesystem, the filesyste_error exception contains
`path` parameters; why should a Filesystem function
that returns `expected` provide access to parameters
that the caller already knows?<br>
<br>
4) `.value()` throws the
`bad_expected_access<T>` template class. Which
means that's the type the user normally has to catch
(when not using `exception_ptr`). Which means that
catching code needs to recognize that the throwing
code was using `expected` to do the throwing. Why
should it?<br>
</div>
</div>
</blockquote>
Why not? future<T> behaves this way. Moving from a
function that returns expected<T> to a function that
returns future<T> will have not too much consequences
on the caller side (if we reach to remove the syntactical
differences - get versus value - or if we provide a monadic
interface and both classes are mapped to model this
concept).<br>
</div>
</blockquote>
<div><br>
`std::future` throws whatever exception was set into the
`promise` it is attached to. The equivalent in `expected`
would be `exception_ptr`.<br>
<br>
And the consequences of using `exception_ptr` in `expected`
are pretty substantial. The code looking at the `expected`
can't tell anything useful about the nature of the error; all
it knows is that some kind of error took place.<br>
</div>
</div>
<br>
</blockquote>
Why?<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------050903060009010200090408--
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Sat, 6 Jun 2015 13:20:02 +0200
Raw View
--Apple-Mail=_EFA8D3CF-2B3E-4977-9FF6-734A0A33B718
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> Il giorno 06/giu/2015, alle ore 07:40, Nicol Bolas <jmckesson@gmail.com> =
ha scritto:
>=20
> On Friday, June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Botet Escriba wro=
te:
> Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit :
>> On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigante wrote:
>>=20
>> C++ is not a functional language, nor is it going to become one in the n=
ear future. What happens in "the strongly typed functional programming worl=
d" is all well and good... for that world. But that alone doesn't make it g=
ood for C++ or any other world.
> Why do you say that C++ is not a functional language? C++ is multi-paradi=
gm language, imperative, object oriented, functional, ...
>=20
> To call something a "functional programming language" requires the inabil=
ity to break the functional paradigm (admittedly, for varying degrees of th=
e word "break"). C++ allows you to restrict yourself, to willingly limit yo=
urself to the functional programming box. What people think of when they sa=
y "functional programming language" doesn't give you the choice; you live w=
ithin the box or write in some other language.
>=20
You misunderstood what functional programming languages are all about.
There are plenty of functional languages that don=E2=80=99t fulfill your de=
finition:
Common Lisp, Scala, F#, Clojure, Ocaml, Erlang, to name a few.
They all allow breaking =E2=80=9Cpurity=E2=80=9D when needed, and have very=
good tools
to do it when you want to. But they encourage the programmer think
in terms of the pure vs IO distinction. Not because they don=E2=80=99t have=
choice,
but because it=E2=80=99s a useful pattern to follow. The only functional la=
nguage (among those used
heavily) that really enforces the purity is Haskell. So if you=E2=80=99re i=
mplying that all
a language that does not enforce purity is not functional, you=E2=80=99re s=
imply wrong.
> That's why C++ is not a functional language. It permits functional progra=
mming, but it doesn't require it.
Again this is true for every functional language used in industry out there=
except haskell
(oh you knew they were used in industry right?)
>> You need to justify this with something more than "this is how things wo=
rk in functional programming monad pattern matching."
> The question is, if expected can be seen as a monad, why don't profit fro=
m all the experience other languages have had with this abstraction.
>=20
> C++ would only be considered to "profit" from this if you see the additio=
n of functional elements to the language as a priori good. I do not see the=
profit in grafting functional elements into C++.
First of all, please understand what a monad is.
=E2=80=9CMonad=E2=80=9D is not a functional programming pattern.=20
The monad is a mathematical concept. A very beautiful and simple to underst=
and mathematical concept.
Saying that the monad is a functional programming pattern is like saying th=
at
eigenvalues are a MATLAB pattern. It=E2=80=99s simply wrong.
It is a concept discovered in the =E2=80=9840s, that had nothing to do with=
programming for decades
(the same as a lot of other theoretical mathematics that turned out useful =
later).
Then it was =E2=80=9Cdiscovered=E2=80=9D in the =E2=80=9890s to be useful i=
n computer science because it abstracts a
lot of programming patterns. Those programming patterns are not =E2=80=9Cfu=
nctional=E2=80=9D.=20
Error handling, logging, Unix pipes, tree and graphs traversals, futures,
input/output, and even nested for loops: all of these very different patter=
ns can be viewed
as concrete instances of some monad. It=E2=80=99s a universal concept, wher=
ever you=E2=80=99re
programming in assembly or in haskell, those patterns _are_ what they are.
The fact is that functional programming languages born after the =E2=80=989=
0s have
embraced this concept as the basis of portions of their syntax, because
this was the way of solving a major problem that functional programming
had at the time (how to enforce purity and still be able to do IO).
That=E2=80=99s why now we associate that concept with functional programmin=
g.
That=E2=80=99s why I=E2=80=99m citing functional programming languages, bec=
ause they
have the expertise in which syntax works better when dealing with
monadic patterns.
Mind that I=E2=80=99m not saying C++ should embrace all of those things. Fo=
r example
there is no sense in using a monadic notation to abstract for loops when we
have, well=E2=80=A6 for loops themselves.
But _if_ we want to understand which are the best ways to
use expected and optionals, which _are_ monads wherever you call them
this way or not, and since the language currently _does not_ have the right
syntax for the task, then we have to pick up the last 25 years of research
and study it, not reinvent the wheel only because =E2=80=9CC++ is not funct=
ional=E2=80=9D.
>> We don't have lambda expressions because they're useful "in functional p=
rogramming"; we have them because it's useful to be able to, quickly and ea=
sily, pass stateful functions to various APIs in C++.
> Labmda expressions are useful by them selves. You have the lambda calculu=
s. This is the base of the functional programming languages.
>=20
> Yes, they are. But as I said, C++ doesn't have them for that reason. C++ =
did not add lambda functions to be the basis of a functional programming mo=
del. It added them because they were useful to many uses of C++, functional=
or not.
>=20
> So you have to provide a reason to do something beyond "that's how functi=
onal programming does it" or "functional languages have something a lot lik=
e that=E2=80=9D.
Nobody has said that the reason is that. An argument by invocation would be=
just wrong.
But the reasons why _they_ have those features remain valid reasons even wh=
en you switch
language.
>> You should not try to turn `expected` into full-frontal "functional prog=
ramming error handling." Ditch the "monads" and "pattern matching" and so f=
orth; just focus on the basic proposal: a return type that is both error co=
de and value.
> Why?
> When we consider sum types it is normal that we consider pattern matching=
, them are undissociated. expected is a sum type. And also a monad. And opt=
ional and future and a lot of classes are monads. So why not make use the w=
hole set of services that are associated.
>=20
> ... Because C++ is not a functional programming language. It has no "sum =
types". It has no "monads". It has no "pattern matching". And it doesn't ne=
ed any of those.
>=20
> Just because C++ has classes that look like certain functional concepts d=
oesn't mean that C++ ought to treat them the way functional languages treat=
them. Like I said before, if you want to argue for these things, you need =
to do so on C++'s terms, not on the terms of a functional language. There m=
ust be some benefit to C++ besides, "that's how functional languages deal w=
ith these.=E2=80=9D
Again we are not talking about functional concepts. We are talking about un=
iversal concepts
that functional programming has embraced and other languages didn=E2=80=99t=
because they didn=E2=80=99t
feel the need. Now the need exists (handling expected/optionals/future/etc=
=E2=80=A6).
>=20
> This "makes the language more robust" only to those who consider the func=
tional programming model to be the one true way of achieving robust code.
Maybe those who think this way have argumentations that you simply ignore?
Ask and you=E2=80=99ll be answered.
If instead you are convinced to be talking with radical extremists I don=E2=
=80=99t understand why you=E2=80=99re discussing at all.
>> Note that expected-style error handling also needs good syntax to be eff=
ectively used and not
>> incur in the same problems: that=E2=80=99s why I advocate it for C++ onl=
y now that we=E2=80=99ll have the monadic
>> 'do notation' provided by the await 2.0 proposal.
>>=20
>> What "await 2.0 proposal" are you referring to? What 'do notation'? I do=
n't see anything like this in N4499.
>>=20
>> Also, something will seriously be wrong in C++ if this becomes legitimat=
e error handling syntax:
>>=20
>> auto b =3D (await (await a).foo()).bar();
>>=20
>> When I look at this, I see syntax that says "stop here until this comple=
tes", not syntax that says, "handle errors that are returned by this expres=
sion."
> You should read again the resumable functions proposal.
>=20
> Which "resumable functions proposal"? The most recent thing on this subje=
ct that I can find (N4499) is pure standardese; trying to figure out what t=
he dozens of changes across dozens of chapters actually means is painful. E=
ven finding out something as simple as what `await` means when applied to a=
n expression is byzantine.
>=20
> If you're talking about N4402, well, that was harder to find, since it's =
not in the repository <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2=
015/>. I managed to find it on isocpp.org <https://isocpp.org/blog/2015/04/=
n4402>. I haven't gone through it in any detail, but I haven't seen the par=
t that said `await` means error handling for `expected`.
>=20
You=E2=80=99re simply not informed so what?
> Equally importantly, what I was referring to was the use of the `await` k=
eyword. Which is intended, by both N4402 and N4499, to be used for some for=
m of delaying of processing, so that a task can be resolved. Hence my use o=
f the phrase, "when I look at this=E2=80=A6=E2=80=9D
>=20
> If you have to tell people, "`await` doesn't mean waiting on something to=
be finished <http://dictionary.reference.com/browse/await?db=3D*>," that's=
suggests pretty strongly that you're using the wrong tool to get a job don=
e.
>> But don't hijack a perfectly good coroutine proposal just to graft `expe=
cted`-based error handling onto it. Make it a separate construct, rather th=
an some kind of Congressional rider amendment that's attached to a must-pas=
s budget appropriations bill.
>>=20
>> That's just disingenuous.
> There is no hijacking at all. The features is defined as it is, and it al=
lows this kind of usage. I could concede that the original proposed feature=
was not intended to managed these cases,
>=20
> That's an admission of hijacking. If something is intended to do X, and t=
hen you make it do Y, where Y is decidedly unlike X in more or less every w=
ay, you have hijacked that something, turning it into a backdoor to get Y a=
ccomplished. You even admitted this when you said, "I would prefer another =
name having less asynchronous connotation." If you'd prefer a different nam=
e, then clearly that something isn't meant to perform that function.
>=20
> It's things like this that got us our current template metaprogramming fu=
nctionality. And while there have been good things that came of it, it requ=
ires such a degree of expert knowledge that only a minority of C++ programm=
ers can use it. Whereas, if it were a designed feature rather than an ad-ho=
c hack, it would have been designed to be more useable.
>=20
If I had any chance to go at a committee meeting I=E2=80=99d propose to mak=
e =E2=80=9Ctry=E2=80=9D and =E2=80=9Cdo=E2=80=9D keywords mean the same as =
=E2=80=9Cawait=E2=80=9D in that context.
That would give the better syntax for any task but maintaining the same und=
erlying abstraction.
And before you call it an hack: we have for loops, range for loops, while l=
oops, do/while loops, which all do the same thing but with different syntax
because it=E2=80=99s convenient.
Anyway, the naming issue with the await keyword is another consequence of a=
part of the C++ world
not being informed of what happens outside, trying to reinvent the wheel=20
(and every community has a part that does the same mistake, let be clear).
If I=E2=80=99d had voice on those proposals I=E2=80=99d separate them in tw=
o different parts: 1) the monadic binding syntax and 2) the specification
of the concurrency-related monads provided by the standard library (futures=
, generators etc=E2=80=A6). That would have been clearer.
Note that anyway I hadn't bothered to propose any of this if it weren=E2=80=
=99t for the resumable functions proposal.=20
And without such syntax being available I would not be so excited about opt=
ional and expected, because they=E2=80=99d
be awkward to use consistently.
But since we _are_ going to get the monadic binding syntax, call it that wa=
y or not, I want to be sure it gets
its value through all the other places where it=E2=80=99s useful.
Greetings,
Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_EFA8D3CF-2B3E-4977-9FF6-734A0A33B718
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">Il giorno 06/giu/201=
5, alle ore 07:40, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com" c=
lass=3D"">jmckesson@gmail.com</a>> ha scritto:</div><br class=3D"Apple-i=
nterchange-newline"><div class=3D""><div dir=3D"ltr" class=3D"">On Friday, =
June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Botet Escriba wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"">Le 05/06/15 18:36, Nicol Bolas a
=C3=A9crit :<br class=3D"">
</div>
<blockquote type=3D"cite" class=3D"">
<div dir=3D"ltr" class=3D"">On Friday, June 5, 2015 at 8:34:24 AM UTC=
-4, Nicola
Gigante wrote:<br class=3D"">
<div class=3D""><br class=3D"">
C++ is not a functional language, nor is it going to become
one in the near future. What happens in "the strongly typed
functional programming world" is all well and good... for that
world. But that <i class=3D"">alone</i> doesn't make it good for =
C++ or
any other world.<br class=3D"">
</div>
</div>
</blockquote>
Why do you say that C++ is not a functional language? C++ is
multi-paradigm language, imperative, object oriented, functional,
...<br class=3D""></div></blockquote><div class=3D""><br class=3D"">To =
call something a "functional programming language" requires the inability t=
o break the functional paradigm (admittedly, for varying degrees of the wor=
d "break"). C++ allows you to restrict yourself, to willingly limit yoursel=
f to the functional programming box. What people think of when they say "fu=
nctional programming language" doesn't give you the choice; you live within=
the box or write in some other language.<br class=3D""><br class=3D""></di=
v></div></div></blockquote><div><br class=3D""></div><div>You misunderstood=
what functional programming languages are all about.</div><div>There are p=
lenty of functional languages that don=E2=80=99t fulfill your definition:</=
div><div>Common Lisp, Scala, F#, Clojure, Ocaml, Erlang, to name a few.</di=
v><div><br class=3D""></div><div>They all allow breaking =E2=80=9Cpurity=E2=
=80=9D when needed, and have very good tools</div><div>to do it when you wa=
nt to. But they encourage the programmer think</div><div>in terms of the pu=
re vs IO distinction. Not because they don=E2=80=99t have choice,</div><div=
>but because it=E2=80=99s a useful pattern to follow. The only functional l=
anguage (among those used</div><div>heavily) that really enforces the purit=
y is Haskell. So if you=E2=80=99re implying that all</div><div>a language t=
hat does not enforce purity is not functional, you=E2=80=99re simply wrong.=
</div><div><br class=3D""></div><br class=3D""><blockquote type=3D"cite" cl=
ass=3D""><div dir=3D"ltr" class=3D""><div class=3D"">That's why C++ is not =
a functional language. It permits functional programming, but it doesn't <i=
class=3D"">require</i> it.<br class=3D""></div></div></blockquote><div><br=
class=3D""></div>Again this is true for every functional language used in =
industry out there except haskell</div><div>(oh you knew they were used in =
industry right?)</div><div><br class=3D""></div><div><blockquote type=3D"ci=
te" class=3D""><div dir=3D"ltr" class=3D""><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote type=3D"cite" class=3D"">
<div dir=3D"ltr" class=3D"">
<div class=3D"">
You need to justify this with something more than "this is how
things work in functional programming monad pattern matching."<br=
class=3D"">
</div>
</div>
</blockquote>
The question is, if expected can be seen as a monad, why don't
profit from all the experience other languages have had with this
abstraction.</div></blockquote><div class=3D""><br class=3D"">C++ would=
only be considered to "profit" from this if you see the addition of functi=
onal elements to the language as a priori good. I do not see the profit in =
grafting functional elements into C++.<br class=3D""></div></div></blockquo=
te><div><br class=3D""></div><div>First of all, please understand what a mo=
nad is.</div><div>=E2=80=9CMonad=E2=80=9D is not a functional programming p=
attern. </div><div>The monad is a mathematical concept. A very beautif=
ul and simple to understand mathematical concept.</div><div><div>Saying tha=
t the monad is a functional programming pattern is like saying that</div><d=
iv>eigenvalues are a MATLAB pattern. It=E2=80=99s simply wrong.</div><div><=
br class=3D""></div></div><div>It is a concept discovered in the =E2=80=984=
0s, that had nothing to do with programming for decades</div><div>(the same=
as a lot of other theoretical mathematics that turned out useful later).</=
div><div>Then it was =E2=80=9Cdiscovered=E2=80=9D in the =E2=80=9890s to be=
useful in computer science because it abstracts a</div><div>lot of program=
ming patterns. Those programming patterns are not =E2=80=9Cfunctional=E2=80=
=9D. </div><div><br class=3D""></div><div>Error handling, logging, Uni=
x pipes, tree and graphs traversals, futures,</div><div>input/output, and e=
ven nested for loops: all of these very different patterns can be viewed</d=
iv><div>as concrete instances of some monad. It=E2=80=99s a universal conce=
pt, wherever you=E2=80=99re</div><div>programming in assembly or in haskell=
, those patterns _are_ what they are.</div><div><br class=3D""></div><div>T=
he fact is that functional programming languages born after the =E2=80=9890=
s have</div><div>embraced this concept as the basis of portions of their sy=
ntax, because</div><div>this was the way of solving a major problem that fu=
nctional programming</div><div>had at the time (how to enforce purity and s=
till be able to do IO).</div><div>That=E2=80=99s why now we associate that =
concept with functional programming.</div><div>That=E2=80=99s why I=E2=80=
=99m citing functional programming languages, because they</div><div>have t=
he expertise in which syntax works better when dealing with</div><div>monad=
ic patterns.</div><div><br class=3D""></div><div>Mind that I=E2=80=99m not =
saying C++ should embrace all of those things. For example</div><div>there =
is no sense in using a monadic notation to abstract for loops when we</div>=
<div>have, well=E2=80=A6 for loops themselves.</div><div><br class=3D""></d=
iv><div>But _if_ we want to understand which are the best ways to</div><div=
>use expected and optionals, which _are_ monads wherever you call them</div=
><div>this way or not, and since the language currently _does not_ have the=
right</div><div>syntax for the task, then we have to pick up the last 25 y=
ears of research</div><div>and study it, not reinvent the wheel only becaus=
e =E2=80=9CC++ is not functional=E2=80=9D.</div><div><br class=3D""></div><=
br class=3D""><blockquote type=3D"cite" class=3D""><div dir=3D"ltr" class=
=3D""><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF"=
text=3D"#000000" class=3D"">
<blockquote type=3D"cite" class=3D"">
<div dir=3D"ltr" class=3D"">
<div class=3D"">
We don't have lambda expressions because they're useful "in
functional programming"; we have them because it's useful to
be able to, quickly and easily, pass stateful functions to
various APIs in C++. </div>
</div>
</blockquote>
Labmda expressions are useful by them selves. You have the lambda
calculus. This is the base of the functional programming languages.</di=
v></blockquote><div class=3D""><br class=3D"">Yes, they are. But as I said,=
C++ doesn't have them <i class=3D"">for that reason</i>. C++ did not add l=
ambda functions to be the basis of a functional programming model. It added=
them because they were useful to <i class=3D"">many uses</i> of C++, funct=
ional or not.<br class=3D""><br class=3D"">So you have to provide a reason =
to do something beyond "that's how functional programming does it" or "func=
tional languages have something a lot like that=E2=80=9D.</div></div></bloc=
kquote><div><br class=3D""></div><div>Nobody has said that the reason is th=
at. An argument by invocation would be just wrong.</div><div>But the reason=
s why _they_ have those features remain valid reasons even when you switch<=
/div><div>language.</div><br class=3D""><blockquote type=3D"cite" class=3D"=
"><div dir=3D"ltr" class=3D""><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote type=3D"cite" class=3D"">
<div dir=3D"ltr" class=3D"">
<div class=3D"">
You should not try to turn `expected` into full-frontal
"functional programming error handling." Ditch the "monads"
and "pattern matching" and so forth; just focus on the basic
proposal: a return type that is both error code and value.<br cla=
ss=3D"">
</div>
</div>
</blockquote>
Why?<br class=3D"">
When we consider sum types it is normal that we consider pattern
matching, them are undissociated. expected is a sum type. And also a
monad. And optional and future and a lot of classes are monads. So
why not make use the whole set of services that are associated.<br clas=
s=3D""></div></blockquote><div class=3D""><br class=3D"">... Because C++ is=
not a functional programming language. It has no "sum types". It has no "m=
onads". It has no "pattern matching". And it doesn't need any of those.<br =
class=3D""><br class=3D"">Just because C++ has classes that look like certa=
in functional concepts doesn't mean that C++ ought to treat them the way fu=
nctional languages treat them. Like I said before, if you want to argue for=
these things, you need to do so on C++'s terms, not on the terms of a func=
tional language. There must be some benefit to C++ besides, "that's how fun=
ctional languages deal with these.=E2=80=9D</div></div></blockquote><div><b=
r class=3D""></div><div>Again we are not talking about functional concepts.=
We are talking about universal concepts</div><div>that functional programm=
ing has embraced and other languages didn=E2=80=99t because they didn=E2=80=
=99t</div><div>feel the need. Now the need exists (handling expected/option=
als/future/etc=E2=80=A6).</div><br class=3D""><blockquote type=3D"cite" cla=
ss=3D""><div dir=3D"ltr" class=3D""><div class=3D""><br class=3D"">This "ma=
kes the language more robust" only to those who consider the functional pro=
gramming model to be the one true way of achieving robust code.<br class=3D=
""></div></div></blockquote><div><br class=3D""></div><div>Maybe those who =
think this way have argumentations that you simply ignore?</div><div>Ask an=
d you=E2=80=99ll be answered.</div><div>If instead you are convinced to be =
talking with radical extremists I don=E2=80=99t understand why you=E2=80=99=
re discussing at all.</div><div><br class=3D""></div><blockquote type=3D"ci=
te" class=3D""><div dir=3D"ltr" class=3D""><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D""><blockquo=
te type=3D"cite" class=3D""><div dir=3D"ltr" class=3D""><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div style=3D"word-wrap:break-word" class=3D""><div =
class=3D""><div class=3D"">Note that expected-style error handling also nee=
ds
good syntax to be effectively used and not</div>
<div class=3D"">incur in the same problems: that=E2=80=99s wh=
y I advocate it
for C++ only now that we=E2=80=99ll have the monadic</div>
<div class=3D"">'do notation' provided by the await 2.0 propo=
sal.</div>
</div>
</div>
</blockquote>
<div class=3D""><br class=3D"">
What "await 2.0 proposal" are you referring to? What 'do
notation'? I don't see anything like this in N4499.<br class=3D""=
>
<br class=3D"">
Also, something will seriously be wrong in C++ if this becomes
legitimate error handling syntax:<br class=3D"">
<br class=3D"">
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px;word-wrap:break-word" clas=
s=3D""><code class=3D"">
<div class=3D""><span style=3D"color:#008" class=3D"">auto</s=
pan><span style=3D"" class=3D""> b </span><span style=3D"color:#660" class=
=3D"">=3D</span><span style=3D"" class=3D""> </span><span style=3D"color:#6=
60" class=3D"">(</span><span style=3D"" class=3D"">await
</span><span style=3D"color:#660" class=3D"">(</span><span =
style=3D"" class=3D"">await a</span><span style=3D"color:#660" class=3D"">)=
..</span><span style=3D"" class=3D"">foo</span><span style=3D"color:#660" cl=
ass=3D"">()).</span><span style=3D"" class=3D"">bar</span><span style=3D"co=
lor:#660" class=3D"">();</span></div>
</code></div>
<br class=3D"">
When I look at this, I see syntax that says "stop here until
this completes", not syntax that says, "handle errors that are
returned by this expression." </div>
</div>
</blockquote>
You should read again the resumable functions proposal.</div></blockquo=
te><div class=3D""><br class=3D""><i class=3D"">Which</i> "resumable functi=
ons proposal"? The most recent thing on this subject that I can find (N4499=
) is pure standardese; trying to figure out what the dozens of changes acro=
ss dozens of chapters actually means is painful. Even finding out something=
as simple as what `await` means when applied to an expression is byzantine=
..<br class=3D""><br class=3D"">If you're talking about N4402, well, that wa=
s harder to find, since it's not in <a href=3D"http://www.open-std.org/JTC1=
/SC22/WG21/docs/papers/2015/" class=3D"">the repository</a>. I managed to f=
ind it<a href=3D"https://isocpp.org/blog/2015/04/n4402" class=3D""> on isoc=
pp.org</a>. I haven't gone through it in any detail, but I haven't seen the=
part that said `await` means error handling for `expected`.<br class=3D"">=
<br class=3D""></div></div></blockquote><div><br class=3D""></div><div>You=
=E2=80=99re simply not informed so what?</div><br class=3D""><blockquote ty=
pe=3D"cite" class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">Equally =
importantly, what I was referring to was the use of the `await` keyword. Wh=
ich is intended, by both N4402 and N4499, to be used for some form of delay=
ing of processing, so that a task can be resolved. Hence my use of the phra=
se, "when I <i class=3D"">look</i> at this=E2=80=A6=E2=80=9D</div></div></b=
lockquote><blockquote type=3D"cite" class=3D""><div dir=3D"ltr" class=3D"">=
<div class=3D""><br class=3D""></div></div></blockquote></div><div><blockqu=
ote type=3D"cite" class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">If=
you have to tell people, "`await` doesn't mean <a href=3D"http://dictionar=
y.reference.com/browse/await?db=3D*" class=3D"">waiting on something to be =
finished</a>," that's suggests pretty strongly that you're using the wrong =
tool to get a job done.<br class=3D""></div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote type=3D"cite" class=3D"">
<div dir=3D"ltr" class=3D"">
<div class=3D"">But don't hijack a perfectly good coroutine proposa=
l just
to graft `expected`-based error handling onto it. Make it a
separate construct, rather than some kind of Congressional
rider amendment that's attached to a must-pass budget
appropriations bill.<br class=3D"">
<br class=3D"">
That's just disingenuous.<br class=3D"">
</div>
</div>
</blockquote>
There is no hijacking at all. The features is defined as it is, and
it allows this kind of usage. I could concede that the original
proposed feature was not intended to managed these cases,</div></blockq=
uote><div class=3D""><br class=3D"">That's an admission of hijacking. If so=
mething is intended to do X, and then you make it do Y, where Y is decidedl=
y unlike X in more or less every way, you have <i class=3D"">hijacked</i> t=
hat something, turning it into a backdoor to get Y accomplished. You even a=
dmitted this when you said, "I
would prefer another name having less asynchronous connotation." If you=
'd prefer a different name, then clearly that something isn't meant to perf=
orm that function.<br class=3D""><br class=3D"">It's things like this that =
got us our current template metaprogramming functionality. And while there =
have been good things that came of it, it requires such a degree of expert =
knowledge that only a minority of C++ programmers can use it. Whereas, if i=
t were a designed feature rather than an ad-hoc hack, it would have been de=
signed to be more useable.<br class=3D""></div></div><div class=3D""><br cl=
ass=3D"webkit-block-placeholder"></div></blockquote><div><br class=3D""></d=
iv><div><div>If I had any chance to go at a committee meeting I=E2=80=99d p=
ropose to make =E2=80=9Ctry=E2=80=9D and =E2=80=9Cdo=E2=80=9D keywords mean=
the same as =E2=80=9Cawait=E2=80=9D in that context.</div><div>That would =
give the better syntax for any task but maintaining the same underlying abs=
traction.</div><div>And before you call it an hack: we have for loops, rang=
e for loops, while loops, do/while loops, which all do the same thing but w=
ith different syntax</div><div>because it=E2=80=99s convenient.</div><div><=
br class=3D""></div><div>Anyway, the naming issue with the await keyword is=
another consequence of a part of the C++ world</div><div>not being informe=
d of what happens outside, trying to reinvent the wheel </div><div>(an=
d every community has a part that does the same mistake, let be clear).</di=
v><div>If I=E2=80=99d had voice on those proposals I=E2=80=99d separate the=
m in two different parts: 1) the monadic binding syntax and 2) the specific=
ation</div><div>of the concurrency-related monads provided by the standard =
library (futures, generators etc=E2=80=A6). That would have been clearer.</=
div><div><br class=3D""></div><div>Note that anyway I hadn't bothered to pr=
opose any of this if it weren=E2=80=99t for the resumable functions proposa=
l. </div><div>And without such syntax being available I would not be s=
o excited about optional and expected, because they=E2=80=99d</div><div>be =
awkward to use consistently.</div><div>But since we _are_ going to get the =
monadic binding syntax, call it that way or not, I want to be sure it gets<=
/div><div>its value through all the other places where it=E2=80=99s useful.=
</div><div><br class=3D""></div></div><div>Greetings,</div><div>Nicola</div=
></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_EFA8D3CF-2B3E-4977-9FF6-734A0A33B718--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 7 Jun 2015 00:40:18 -0700 (PDT)
Raw View
------=_Part_1109_137183782.1433662818758
Content-Type: multipart/alternative;
boundary="----=_Part_1110_1397870843.1433662818759"
------=_Part_1110_1397870843.1433662818759
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, June 6, 2015 at 7:00:03 AM UTC-4, Vicente J. Botet Escriba=20
wrote:
>
> Le 06/06/15 09:19, Nicol Bolas a =C3=A9crit :
> =20
> On Friday, June 5, 2015 at 6:42:30 PM UTC-4, Matthew Woehlke wrote:=20
>>
>> On 2015-06-05 17:34, Vicente J. Botet Escriba wrote:=20
>> > Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :=20
>> >> OK, so... what about static analysis tools? We already have great=20
>> >> static tools that can detect the use of many uninitialized values.=20
>> >=20
>> > expected as optional, and I hope would variant, are never uninitialize=
d=20
>> > as these classes have default constructor.=20
>>
>> Not the expected/optional itself, but the contained value.=20
>>
>> IOW, this is a (potential) error:=20
>>
>> auto x =3D function_that_returns_expected_or_optional;=20
>> do_something(x.value());=20
>>
>> ...because you didn't check that 'x' actually *has* a value, and thus=20
>> value() might throw.=20
>>
>> Nicol is of the opinion that one should never write code like this, even=
=20
>> if throwing from the context where value() is called if there is no=20
>> value is the intended behavior.=20
>>
>> I have to ask, though: in that case, why throw at all?
>>
>
> Because "wrong" doesn't necessarily mean "shouldn't be allowed."
>
> Sometimes, some piece of code winds up with an `expected` that doesn't=20
> have its value, and that code's precondition is that it should have a=20
> value. The code doesn't check it because it shouldn't be possible, but=20
> maybe they've done something that defeats the static analysis tool (or=20
> their compiler isn't smart enough to find it for them). But for whatever=
=20
> reason, this code bug has happened.
>
> if there is a precondition that there is a value, the function should=
=20
> take a T as parameter not an expected<T>.
>
You're assuming it's a "function" rather than just "code". A particular=20
piece of code has preconditions too, things that it assumes have happened,=
=20
so it doesn't check for them.
> Really, I envision expected as a 'delayed throw' mechanism. The point=
=20
>> is=20
>> to return an expected instead of throwing immediately, and instead delay=
=20
>> *the throw that otherwise would have happened* until the user calls=20
>> value(), thus giving a window where the user can choose to handle the=20
>> error before an exception is thrown.
>>
>
> Well, a lot of the functional programming crowd in this thread seems to=
=20
> think that `expected` objects should be flying up the call-stack via=20
> `await` shenanigans or whatever. So there's some disagreement here as to=
=20
> how `expected` ought to be used.
>
> Why you want to tell to the user how it must use expected? This is not=
=20
> up to the standard.
>
Of course it is. It's a decision of the standard to allow `value` to throw=
=20
at all. Therefore, the standard says how you can use `value`.
People are suggesting that `await` should be grafted onto `expected` as=20
well. Others are suggesting some "pattern matching" syntax or some such.=20
These are all very much ways the standard tells users how a type may be=20
used.
=20
> I see `expected` as how I described it in my look at it: an alternate=20
> way to pass an error directly to the local calling scope.
>
> There are several problems with thinking of `expected` as merely a delaye=
d=20
> throwing mechanic. Part of it has to do with what goes into the error cod=
e=20
> portion.
>
> As previously stated, exceptions often need rich information, since they=
=20
> are usually processed far from their invocation site. `expected` objects=
=20
> are usually processed close enough that the local code can get much of th=
is=20
> information themselves. In those cases, a simple std::error_condition is=
=20
> often sufficient.
>
> Something like `exception_ptr` is completely opaque; the only thing you=
=20
> can do with that is throw it. You can't inspect it to find out which=20
> exception was captured or anything. Even a shared pointer to some object =
is=20
> problematic because you're having to allocate memory just to pass an erro=
r.
> =20
> std::variant is an valid alternative. It is equivalent to exception=20
> specifications. I prefer yet std::any that as the ABI don't changes when=
=20
> new errors are added. Neither of them forces an allocation.
>
std::any very much does do memory allocation. Oh, implementations may have=
=20
some small-object-optimization in its storage. But that's a QOI issue; just=
read=20
the spec=20
<http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4480.html#any.cla=
ss>.=20
Implementations "should avoid the use of dynamically allocated memory for a=
=20
small contained object". How big "small" is is a QOI issue. And since we're=
=20
talking about arbitrary objects, you can't guarantee that.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1110_1397870843.1433662818759
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, June 6, 2015 at 7:00:03 AM UTC-4, Vic=
ente J. Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 06/06/15 09:19, Nicol Bolas a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 6:42:30 PM UTC-4,
Matthew Woehlke wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">On
2015-06-05 17:34, Vicente J. Botet Escriba wrote:
<br>
> Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
<br>
>> OK, so... what about static analysis tools? We
already have great
<br>
>> static tools that can detect the use of many
uninitialized values.
<br>
>
<br>
> expected as optional, and I hope would variant, are never
uninitialized
<br>
> as these classes have default constructor.
<br>
<br>
Not the expected/optional itself, but the contained value.
<br>
<br>
IOW, this is a (potential) error:
<br>
<br>
auto x =3D function_that_returns_<wbr>expected_or_optional=
;
<br>
do_something(x.value());
<br>
<br>
...because you didn't check that 'x' actually *has* a value,
and thus
<br>
value() might throw.
<br>
<br>
Nicol is of the opinion that one should never write code like
this, even
<br>
if throwing from the context where value() is called if there
is no
<br>
value is the intended behavior.
<br>
<br>
I have to ask, though: in that case, why throw at all?<br>
</blockquote>
<div><br>
Because "wrong" doesn't necessarily mean "shouldn't be
allowed."<br>
<br>
Sometimes, some piece of code winds up with an `expected` that
doesn't have its value, and that code's precondition is that
it should have a value. The code doesn't check it because it
shouldn't be possible, but maybe they've done something that
defeats the static analysis tool (or their compiler isn't
smart enough to find it for them). But for whatever reason,
this code bug has happened.<br>
<br>
</div>
</div>
</blockquote>
if there is a precondition that there is a value, the function
should take a T as parameter not an expected<T>.<br></div></block=
quote><div><br>You're assuming it's a "function" rather than just "code". A=
particular piece of code has preconditions too, things that it assumes hav=
e happened, so it doesn't check for them.<br></div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
Really, I envision expected as a 'delayed throw' mechanism.
The point is
<br>
to return an expected instead of throwing immediately, and
instead delay
<br>
*the throw that otherwise would have happened* until the user
calls
<br>
value(), thus giving a window where the user can choose to
handle the
<br>
error before an exception is thrown.<br>
</blockquote>
<div><br>
Well, a lot of the functional programming crowd in this thread
seems to think that `expected` objects should be flying up the
call-stack via `await` shenanigans or whatever. So there's
some disagreement here as to how `expected` ought to be used.<br>
<br>
</div>
</div>
</blockquote>
Why you want to tell to the user how it must use expected? This is
not up to the standard.<br></div></blockquote><div><br>Of course it is.=
It's a decision of the standard to allow `value` to throw at all. Therefor=
e, the standard says how you can use `value`.<br><br>People are suggesting =
that `await` should be grafted onto `expected` as well. Others are suggesti=
ng some "pattern matching" syntax or some such. These are all very much way=
s the standard tells users how a type may be used.<br> </div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#00000=
0">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>I see `expected` as how I described it in my look at it: an
alternate way to pass an error directly to the local calling
scope.<br>
<br>
There are several problems with thinking of `expected` as
merely a delayed throwing mechanic. Part of it has to do with
what goes into the error code portion.<br>
<br>
As previously stated, exceptions often need rich information,
since they are usually processed far from their invocation
site. `expected` objects are usually processed close enough
that the local code can get much of this information
themselves. In those cases, a simple std::error_condition is
often sufficient.<br>
<br>
Something like `exception_ptr` is completely opaque; the only
thing you can do with that is throw it. You can't inspect it
to find out which exception was captured or anything. Even a
shared pointer to some object is problematic because you're
having to allocate memory just to pass an error.<br>
</div>
</div>
</blockquote>
std::variant is an valid alternative. It is equivalent to exception
specifications. I prefer yet std::any that as the ABI don't changes
when new errors are added. Neither of them forces an allocation.<br></d=
iv></blockquote><div><br>std::any very much does do memory allocation. Oh, =
implementations may have some small-object-optimization in its storage. But=
that's a QOI issue; just <a href=3D"http://www.open-std.org/JTC1/SC22/WG21=
/docs/papers/2015/n4480.html#any.class">read the spec</a>. Implementations =
"should avoid the use of dynamically allocated memory for a small contained=
object". How big "small" is is a QOI issue. And since we're talking about =
arbitrary objects, you can't guarantee that.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1110_1397870843.1433662818759--
------=_Part_1109_137183782.1433662818758--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 7 Jun 2015 00:48:24 -0700 (PDT)
Raw View
------=_Part_1116_1149870225.1433663304881
Content-Type: multipart/alternative;
boundary="----=_Part_1117_663532222.1433663304881"
------=_Part_1117_663532222.1433663304881
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, June 6, 2015 at 7:04:02 AM UTC-4, Vicente J. Botet Escriba=20
wrote:
>
> Le 06/06/15 09:24, Nicol Bolas a =C3=A9crit :
> =20
> On Saturday, June 6, 2015 at 3:08:28 AM UTC-4, Vicente J. Botet Escriba=
=20
> wrote:=20
>>
>> Le 05/06/15 20:13, Nicol Bolas a =C3=A9crit :
>> =20
>> On Friday, June 5, 2015 at 1:40:33 PM UTC-4, Matthew Woehlke wrote:
>>
>> Why not? future<T> behaves this way. Moving from a function that returns=
=20
>> expected<T> to a function that returns future<T> will have not too much=
=20
>> consequences on the caller side (if we reach to remove the syntactical=
=20
>> differences - get versus value - or if we provide a monadic interface an=
d=20
>> both classes are mapped to model this concept).
>>
>> =20
> `std::future` throws whatever exception was set into the `promise` it is=
=20
> attached to. The equivalent in `expected` would be `exception_ptr`.
>
> And the consequences of using `exception_ptr` in `expected` are pretty=20
> substantial. The code looking at the `expected` can't tell anything usefu=
l=20
> about the nature of the error; all it knows is that some kind of error to=
ok=20
> place.
> =20
> Why?
>
Have you actually looked at what is laughably called the interface to=20
`exception_ptr` <http://en.cppreference.com/w/cpp/error/exception_ptr>?=20
Outside of pointer-like behavior, there is only one thing you can do with=
=20
one: throw it.
That's it.
So explain how a user could possibly learn anything about the nature of an=
=20
exception from that. Without actually throwing it, of course.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1117_663532222.1433663304881
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 6, 2015 at 7:04:02 AM UTC-4, Vicente J. =
Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 06/06/15 09:24, Nicol Bolas a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Saturday, June 6, 2015 at 3:08:28 AM UTC-4,
Vicente J. Botet Escriba wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 20:13, Nicol Bolas a =C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">On Friday, June 5, =
2015 at 1:40:33 PM
UTC-4, Matthew Woehlke wrote:</div></blockquote></div></blo=
ckquote></div></blockquote></div></blockquote><div></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000"><bloc=
kquote type=3D"cite"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div bgcolor=3D"#FFFFFF" text=3D"#000000"><blockquote type=3D"cite"><div=
bgcolor=3D"#FFFFFF" text=3D"#000000">Why not? future<T> behaves this=
way. Moving from a
function that returns expected<T> to a function that
returns future<T> will have not too much consequences
on the caller side (if we reach to remove the syntactical
differences - get versus value - or if we provide a monadic
interface and both classes are mapped to model this
concept).<br>
</div></blockquote></div></blockquote></div></blockquote></div></=
blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FF=
FFFF" text=3D"#000000"><blockquote type=3D"cite"></blockquote><blockquote t=
ype=3D"cite"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote>
<div><br>
`std::future` throws whatever exception was set into the
`promise` it is attached to. The equivalent in `expected`
would be `exception_ptr`.<br>
<br>
And the consequences of using `exception_ptr` in `expected`
are pretty substantial. The code looking at the `expected`
can't tell anything useful about the nature of the error; all
it knows is that some kind of error took place.<br>
</div>
</div>
<br>
</blockquote>
Why?<br></div></blockquote><div><br>Have you actually <a href=3D"http:/=
/en.cppreference.com/w/cpp/error/exception_ptr">looked at what is laughably=
called the interface to `exception_ptr`</a>? Outside of pointer-like behav=
ior, there is only one thing you can do with one: throw it.<br><br>That's i=
t.<br><br>So explain how a user could possibly learn anything about the nat=
ure of an exception from that. Without actually throwing it, of course.<br>=
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1117_663532222.1433663304881--
------=_Part_1116_1149870225.1433663304881--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 7 Jun 2015 01:24:27 -0700 (PDT)
Raw View
------=_Part_1114_307705209.1433665467962
Content-Type: multipart/alternative;
boundary="----=_Part_1115_460825687.1433665467962"
------=_Part_1115_460825687.1433665467962
Content-Type: text/plain; charset=UTF-8
On Saturday, June 6, 2015 at 5:16:06 AM UTC-4, Sean Middleditch wrote:
>
> On Saturday, June 6, 2015 at 12:24:31 AM UTC-7, Nicol Bolas wrote:
>
The approach mentioned in previous posts were not brought up "because
> functional languages do it." They're because the options presented for C++
> thus far are all inadequate for a significant portion of the primary
> "customers" of the language. And that's frustrating because we _know_ it
> can be better (if not perfect) as we have clear examples of better ways of
> doing things. All one must do is look over at those dirty
> functional-programmer hippies and pay attention for a few of them (hey,
> many of them have exceptions _too_; turns out they're not all that
> different from us!).
>
> There is a very huge difference between it being merely a possibility to
> write code that dodges landmines rather than being strongly guided towards
> writing code that is obvious, clear, and does exactly what it says upon
> cursory inspection.
>
> Return codes make incidental mistakes (even for experienced experts)
> easier than writing robust code. Exceptions make incidental screwups (even
> for experienced experts) easier than writing robust code. BOTH methods
> result in degraded productivity, poor user experiences, and lost profits.
>
Now, I'm starting to understand.
You believe that C++ error handling, *of all kinds*, is fundamentally
broken. And thus, the only way to fix it is to create an entirely new
paradigm, along with a bunch of new syntactic stuff added on, which is
based on stuff taken from functional programming. Because you think that
functional error resolution is just awesome and works better than anything
in C++.
I believe that C++ error handling is quite good, but has some holes in it.
`expected` plugs one of the biggest: allowing the user to request local
error resolution for returned values, in a way that makes that as easy on
the user to implement as possible.
You want to turn `expected` into the one true way to handle errors.
I've learned a lot in my years of programming. One of the most important
lessons is this: never trust "the one true way" to do *anything*. "The one
true way" led to things like iostream. To uniform initialization syntax
that you can't use uniformly. And so forth.
Just as there's no such thing as a free lunch, "the one true way" never is.
Also, I'd love to see some evidence that "a significant portion of the
primary 'customers' of the language" find exceptions and/or the current
incarnation of `expected` to be "inadequate".
That damage can't be undone, but we can stop willfully inflicting more of
> it out of our own stubborn refusal to admit that C++ today is not the best
> language, nor even the best C++.
>
> Now, certainly, the things I previously mentioned don't solve all
> problems. I don't claim to be a genius with a perfect solution for every
> problem. I was at least hoping to tap into the minds of other smart people
> who might be willing to work through those problems and potential
> solutions. Not what I'm going to get, apparently.
>
Of course not. Because we don't believe that error handling in C++ is
fundamentally broken. You shouldn't expect other people to agree with such
extreme positions. Or at least, not in any real quantity.
We know - and have ample proof - that there are more options for handling
> errors than just either return values or exceptions. Yet that's what every
> discussion about error handling in C++ turns into: a choice between bad or
> suboptimal.
>
.... `expected` *is a return value*. You want to call it something else, but
that's what it is.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1115_460825687.1433665467962
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 6, 2015 at 5:16:06 AM UTC-4, Sean Middle=
ditch wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>On Saturday, =
June 6, 2015 at 12:24:31 AM UTC-7, Nicol Bolas wrote:<br></div></blockquote=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div>T=
he approach mentioned in previous posts were not brought up "because functi=
onal languages do it." They're because the options presented for C++ thus f=
ar are all inadequate for a significant portion of the primary "customers" =
of the language. And that's frustrating because we _know_ it can be better =
(if not perfect) as we have clear examples of better ways of doing things. =
All one must do is look over at those dirty functional-programmer hippies a=
nd pay attention for a few of them (hey, many of them have exceptions _too_=
; turns out they're not all that different from us!).<div><br></div><div>Th=
ere is a very huge difference between it being merely a possibility to writ=
e code that dodges landmines rather than being strongly guided towards writ=
ing code that is obvious, clear, and does exactly what it says upon cursory=
inspection.</div><div><br></div><div>Return codes make incidental mistakes=
(even for experienced experts) easier than writing robust code. Exceptions=
make incidental screwups (even for experienced experts) easier than writin=
g robust code. BOTH methods result in degraded productivity, poor user expe=
riences, and lost profits.</div></div></blockquote><div><br>Now, I'm starti=
ng to understand.<br><br>You believe that C++ error handling, <i>of all kin=
ds</i>, is fundamentally broken. And thus, the only way to fix it is to cre=
ate an entirely new paradigm, along with a bunch of new syntactic stuff add=
ed on, which is based on stuff taken from functional programming. Because y=
ou think that functional error resolution is just awesome and works better =
than anything in C++.<br><br>I believe that C++ error handling is quite goo=
d, but has some holes in it. `expected` plugs one of the biggest: allowing =
the user to request local error resolution for returned values, in a way th=
at makes that as easy on the user to implement as possible.<br><br>You want=
to turn `expected` into the one true way to handle errors.<br><br>I've lea=
rned a lot in my years of programming. One of the most important lessons is=
this: never trust "the one true way" to do <i>anything</i>. "The one true =
way" led to things like iostream. To uniform initialization syntax that you=
can't use uniformly. And so forth.<br><br>Just as there's no such thing as=
a free lunch, "the one true way" never is.<br><br>Also, I'd love to see so=
me evidence that "a significant portion of the primary 'customers' of the l=
anguage" find exceptions and/or the current incarnation of `expected` to be=
"inadequate".<br><br></div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr"><div></div><div>That damage can't be undone, but we can stop=
willfully inflicting more of it out of our own stubborn refusal to admit t=
hat C++ today is not the best language, nor even the best C++.</div><div><b=
r></div><div>Now, certainly, the things I previously mentioned don't solve =
all problems. I don't claim to be a genius with a perfect solution for ever=
y problem. I was at least hoping to tap into the minds of other smart peopl=
e who might be willing to work through those problems and potential solutio=
ns. Not what I'm going to get, apparently.</div></div></blockquote><div><br=
>Of course not. Because we don't believe that error handling in C++ is fund=
amentally broken. You shouldn't expect other people to agree with such extr=
eme positions. Or at least, not in any real quantity.<br><br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>We know - and ha=
ve ample proof - that there are more options for handling errors than just =
either return values or exceptions. Yet that's what every discussion about =
error handling in C++ turns into: a choice between bad or suboptimal.</div>=
</div></blockquote><div><br>... `expected` <i>is a return value</i>. You wa=
nt to call it something else, but that's what it is.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1115_460825687.1433665467962--
------=_Part_1114_307705209.1433665467962--
.
Author: Sean Middleditch <sean@middleditch.us>
Date: Sun, 7 Jun 2015 02:26:41 -0700
Raw View
On Sun, Jun 7, 2015 at 1:24 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Now, I'm starting to understand.
Yay, progress!
>
> You believe that C++ error handling, of all kinds, is fundamentally broken.
I'd say "insufficient," but yes.
> And thus, the only way to fix it is to create an entirely new paradigm,
> along with a bunch of new syntactic stuff added on, which is based on stuff
> taken from functional programming. Because you think that functional error
Sort of.
I'm saying that there are many other reasons we already want these
things and hence why things like
http://www.stroustrup.com/OpenPatternMatching.pdf are under active
research. Since we're _already_ going down that route, we might as
well look forward and anticipate what it buys us, rather than just
dismissing them foreign un-C++-ican ideas. :)
> resolution is just awesome and works better than anything in C++.
Well, no. Again, most functional languages _also_ have exceptions. For a reason.
From my perspective, it's because they haven't yet found a better
solution. I believe that from yours, it's because exceptions are a
great solution. And again, we're just going to disagree. :)
> I believe that C++ error handling is quite good, but has some holes in it.
Then we disagree, and I don't see either of us budging on this one. :)
> `expected` plugs one of the biggest: allowing the user to request local
> error resolution for returned values, in a way that makes that as easy on
> the user to implement as possible.
And I don't think it's "as easy to implement as possible." Better than
what we have today, yes. Still a bit rinky-dink, though.
> You want to turn `expected` into the one true way to handle errors.
Nope. We've diverged in understanding again. :)
It can be the better way to handle a certain large class of errors. I
think it's better than what we have today in most cases.
But it doesn't solve all cases. Which is a problem. Because those
cases are still insufficiently handled, from my perspective.
So I want to talk about them. If you don't want to talk about them,
that's ok; I'm still going to. I'll unhijack your thread for that,
though (sorry about that, btw).
> I've learned a lot in my years of programming. One of the most important
> lessons is this: never trust "the one true way" to do anything. "The one
I also have decades of experience, and also learn things sometimes,
and also have a couple pearls of wisdom to dispense. We have a lot in
common after all! ;)
"The one true way" has a mixed history, I'll grant you that. :)
My years have taught me that non-holistic approaches to design lead to
excessive layers of duct-tape and leftover load-bearing scaffolding.
C++ has several examples thereof. map and unordered_map are two of the
easier examples.
> true way" led to things like iostream. To uniform initialization syntax that
> you can't use uniformly. And so forth.
I think there's some misattribution there, but I assent to your point.
In any case, I think you already identified our key contention. I
strongly believe that C++ has grossly insufficient ways to deal with
errors; you strongly believe C++'s mechanisms are mostly fine as they
are. I don't think either of us are going to convince the other.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 7 Jun 2015 03:08:20 -0700 (PDT)
Raw View
------=_Part_45_96815468.1433671700950
Content-Type: multipart/alternative;
boundary="----=_Part_46_1532449897.1433671700950"
------=_Part_46_1532449897.1433671700950
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, June 6, 2015 at 7:20:09 AM UTC-4, Nicola Gigante wrote:
>
> Il giorno 06/giu/2015, alle ore 07:40, Nicol Bolas <jmck...@gmail.com=20
> <javascript:>> ha scritto:
>
> On Friday, June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Botet Escriba=20
> wrote:
>>
>> Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit :
>> =20
>> On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigante wrote:
>>
>> C++ is not a functional language, nor is it going to become one in the=
=20
>> near future. What happens in "the strongly typed functional programming=
=20
>> world" is all well and good... for that world. But that *alone* doesn't=
=20
>> make it good for C++ or any other world.
>> =20
>> Why do you say that C++ is not a functional language? C++ is=20
>> multi-paradigm language, imperative, object oriented, functional, ...
>>
>
> To call something a "functional programming language" requires the=20
> inability to break the functional paradigm (admittedly, for varying degre=
es=20
> of the word "break"). C++ allows you to restrict yourself, to willingly=
=20
> limit yourself to the functional programming box. What people think of wh=
en=20
> they say "functional programming language" doesn't give you the choice; y=
ou=20
> live within the box or write in some other language.
>
>
> You misunderstood what functional programming languages are all about.
> There are plenty of functional languages that don=E2=80=99t fulfill your=
=20
> definition:
> Common Lisp, Scala, F#, Clojure, Ocaml, Erlang, to name a few.
>
*ahem*: "admittedly, for varying degrees of the word 'break'." That's what=
=20
I'm referring to.
The fact that these languages let you out of the box sometimes doesn't=20
change the fact that the box exists. Your home is still that box.
In C++, you don't live in a box. Save for one you construct for yourself.
> You need to justify this with something more than "this is how things=
=20
>> work in functional programming monad pattern matching."
>> =20
>> The question is, if expected can be seen as a monad, why don't profit=20
>> from all the experience other languages have had with this abstraction.
>>
>
> C++ would only be considered to "profit" from this if you see the additio=
n=20
> of functional elements to the language as a priori good. I do not see the=
=20
> profit in grafting functional elements into C++.
>
>
> First of all, please understand what a monad is.
> =E2=80=9CMonad=E2=80=9D is not a functional programming pattern.=20
> The monad is a mathematical concept. A very beautiful and simple to=20
> understand mathematical concept.
> Saying that the monad is a functional programming pattern is like saying=
=20
> that
> eigenvalues are a MATLAB pattern. It=E2=80=99s simply wrong.
>
> It is a concept discovered in the =E2=80=9840s, that had nothing to do wi=
th=20
> programming for decades
> (the same as a lot of other theoretical mathematics that turned out usefu=
l=20
> later).
> Then it was =E2=80=9Cdiscovered=E2=80=9D in the =E2=80=9890s to be useful=
in computer science=20
> because it abstracts a
> lot of programming patterns. Those programming patterns are not=20
> =E2=80=9Cfunctional=E2=80=9D.=20
>
> Error handling, logging, Unix pipes, tree and graphs traversals, futures,
> input/output, and even nested for loops: all of these very different=20
> patterns can be viewed
> as concrete instances of some monad. It=E2=80=99s a universal concept, wh=
erever=20
> you=E2=80=99re
> programming in assembly or in haskell, those patterns _are_ what they are=
..
>
Yes. Those patterns are error handling, logging, Unix pipes, tree and=20
graphs traversals, futures,input/output, and even nested for loops. The=20
fact that you can come up with a definition that manages to model all of=20
them does not change the fact that *they're all different things*.
Just because you can group them as though they were all the same doesn't=20
mean you should.
The fact is that functional programming languages born after the =E2=80=989=
0s have
> embraced this concept as the basis of portions of their syntax, because
> this was the way of solving a major problem that functional programming
> had at the time (how to enforce purity and still be able to do IO).
> That=E2=80=99s why now we associate that concept with functional programm=
ing.
> That=E2=80=99s why I=E2=80=99m citing functional programming languages, b=
ecause they
> have the expertise in which syntax works better when dealing with
> monadic patterns.
>
> Mind that I=E2=80=99m not saying C++ should embrace all of those things. =
For=20
> example
> there is no sense in using a monadic notation to abstract for loops when =
we
> have, well=E2=80=A6 for loops themselves.
>
> But _if_ we want to understand which are the best ways to
> use expected and optionals, which _are_ monads wherever you call them
> this way or not, and since the language currently _does not_ have the rig=
ht
> syntax for the task, then we have to pick up the last 25 years of researc=
h
> and study it, not reinvent the wheel only because =E2=80=9CC++ is not fun=
ctional=E2=80=9D.
>
And therein lies the problem.
What justification do you provide that these objects should be manipulated=
=20
as monads at all?
After all, you've conceded that "the best way" to handle certain monads is=
=20
to use native syntax for them, rather than some monad thing. So why not do=
=20
the same things for these objects? Why do you *insist* on treating them as=
=20
monads as a category of entirely dissimilar constructs, rather than as=20
individual dissimilar constructs?
The best way to use anything is the way that most directly and effectively=
=20
solves your problem. `optional` is a type that exists to represent an=20
object which may or may not exist. And thus, the best interface is one that=
=20
allows you to use that concept to solve problems surrounding values that=20
may or may not exists.
That `optional` *just so happens* to be able to be classified as a monad is=
=20
*irrelevant* to the goal of the class. `optional` isn't defined the way it=
=20
is because it is a monad; that's merely an accident. The fact that=20
`optional` could be manipluated as a monad does not *a priori* justify that=
=20
it *should* be manipulated in this fashion. Only a legitimate reason to do=
=20
so, within the concept of having optional values, would justify such an=20
interface.
`optional` could "technically" be considered a container too; that doesn't=
=20
mean we should start getting iterators to an `optional` array.
And the same goes for `expected`. This type exists to represent a means of=
=20
a function erroring out that has failed, needs to report that failure,=20
wants to do so to the local caller scope, and needs to provide additional=
=20
information beyond the fact of the failure itself.
Again, the fact that `expected` technically is a monad doesn't mean squat=
=20
to this interface. Not unless you can actually justify using such an=20
interface to handle it.
Functional programming *needs* special syntax for monad manipulation. C++=
=20
does not; it can get by without it. So what is gained by providing such=20
manipulation?
> We don't have lambda expressions because they're useful "in functional=
=20
>> programming"; we have them because it's useful to be able to, quickly an=
d=20
>> easily, pass stateful functions to various APIs in C++.=20
>> =20
>> Labmda expressions are useful by them selves. You have the lambda=20
>> calculus. This is the base of the functional programming languages.
>>
>
> Yes, they are. But as I said, C++ doesn't have them *for that reason*.=20
> C++ did not add lambda functions to be the basis of a functional=20
> programming model. It added them because they were useful to *many uses*=
=20
> of C++, functional or not.
>
> So you have to provide a reason to do something beyond "that's how=20
> functional programming does it" or "functional languages have something a=
=20
> lot like that=E2=80=9D.
>
>
> Nobody has said that the reason is that.
>
You just did. You said very clearly, "we have to pick up the last 25 years=
=20
of research and study it, not reinvent the wheel only because =E2=80=9CC++ =
is not=20
functional=E2=80=9D." You are justifying adding such an interface because o=
f those=20
"25 years of research and study". And where has that been done?
Functional programming languages.
=20
> An argument by invocation would be just wrong.
> But the reasons why _they_ have those features remain valid reasons even=
=20
> when you switch
> language.
>
If that's true, then you ought to be able to explain what those reasons=20
are. In terms of C++ code and C++ examples. Without citing the 25 years of=
=20
divinely-revealed truth.
Remember: you're the one making the extraordinary claim (C++ needs to have=
=20
syntactic facilities to manipulate monads). So its you who needs to provide=
=20
the evidence to back it up.
=20
> If instead you are convinced to be talking with radical extremists I don=
=E2=80=99t=20
> understand why you=E2=80=99re discussing at all.
>
I didn't start this thread to talk about functional programming. I started=
=20
it to share my ideas and principles when it came to error handling. To=20
explain where those views came from, and to see what others thought of=20
them. It was the "radical extremists" who insisted on turning this into a=
=20
thread about how all error handling in C++ is irreparably broken, and the=
=20
one true way to solve it is to graft monad operators to C++ and start=20
having every function that can error return `expected` and for us to litter=
=20
our code with `await` to handle these errors or other similar syntax.
> Note that expected-style error handling also needs good syntax to be=20
>>> effectively used and not
>>> incur in the same problems: that=E2=80=99s why I advocate it for C++ on=
ly now=20
>>> that we=E2=80=99ll have the monadic
>>> 'do notation' provided by the await 2.0 proposal.
>>> =20
>>
>> What "await 2.0 proposal" are you referring to? What 'do notation'? I=20
>> don't see anything like this in N4499.
>>
>> Also, something will seriously be wrong in C++ if this becomes legitimat=
e=20
>> error handling syntax:
>>
>> auto b =3D (await (await a).foo()).bar();
>> =20
>> When I look at this, I see syntax that says "stop here until this=20
>> completes", not syntax that says, "handle errors that are returned by th=
is=20
>> expression."=20
>> =20
>> You should read again the resumable functions proposal.
>>
>
> *Which* "resumable functions proposal"? The most recent thing on this=20
> subject that I can find (N4499) is pure standardese; trying to figure out=
=20
> what the dozens of changes across dozens of chapters actually means is=20
> painful. Even finding out something as simple as what `await` means when=
=20
> applied to an expression is byzantine.
>
> If you're talking about N4402, well, that was harder to find, since it's=
=20
> not in the repository=20
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/>. I managed to=
=20
> find it on isocpp.org <https://isocpp.org/blog/2015/04/n4402>. I haven't=
=20
> gone through it in any detail, but I haven't seen the part that said=20
> `await` means error handling for `expected`.
>
>
> You=E2=80=99re simply not informed so what?
>
So... inform me. You seem to know what these things are. So give me a link.=
=20
Or just explain it here. I clearly looked but didn't find anything=20
particularly enlightening.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_46_1532449897.1433671700950
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, June 6, 2015 at 7:20:09 AM UTC-4, Nicola Giga=
nte wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-w=
rap:break-word"><div><blockquote type=3D"cite"><div>Il giorno 06/giu/2015, =
alle ore 07:40, Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" g=
df-obfuscated-mailto=3D"00ZdmC7KsPYJ" rel=3D"nofollow" onmousedown=3D"this.=
href=3D'javascript:';return true;" onclick=3D"this.href=3D'javascript:';ret=
urn true;">jmck...@gmail.com</a>> ha scritto:</div><br><div><div dir=3D"=
ltr">On Friday, June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Botet Escriba =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 18:36, Nicol Bolas a
=C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola
Gigante wrote:<br>
<div><br>
C++ is not a functional language, nor is it going to become
one in the near future. What happens in "the strongly typed
functional programming world" is all well and good... for that
world. But that <i>alone</i> doesn't make it good for C++ or
any other world.<br>
</div>
</div>
</blockquote>
Why do you say that C++ is not a functional language? C++ is
multi-paradigm language, imperative, object oriented, functional,
...<br></div></blockquote><div><br>To call something a "functional prog=
ramming language" requires the inability to break the functional paradigm (=
admittedly, for varying degrees of the word "break"). C++ allows you to res=
trict yourself, to willingly limit yourself to the functional programming b=
ox. What people think of when they say "functional programming language" do=
esn't give you the choice; you live within the box or write in some other l=
anguage.<br><br></div></div></div></blockquote><div><br></div><div>You misu=
nderstood what functional programming languages are all about.</div><div>Th=
ere are plenty of functional languages that don=E2=80=99t fulfill your defi=
nition:</div><div>Common Lisp, Scala, F#, Clojure, Ocaml, Erlang, to name a=
few.</div></div></div></blockquote><div><br>*ahem*: "admittedly, for varyi=
ng degrees of the word 'break'." That's what I'm referring to.<br><br>The f=
act that these languages let you out of the box sometimes doesn't change th=
e fact that the box exists. Your home is still that box.<br><br>In C++, you=
don't live in a box. Save for one you construct for yourself.<br><br></div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break=
-word"><div><br></div><div><blockquote type=3D"cite"><div dir=3D"ltr"><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div bgcolor=3D"#FFFFFF" text=3D"#000000=
">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
You need to justify this with something more than "this is how
things work in functional programming monad pattern matching."<br=
>
</div>
</div>
</blockquote>
The question is, if expected can be seen as a monad, why don't
profit from all the experience other languages have had with this
abstraction.</div></blockquote><div><br>C++ would only be considered to=
"profit" from this if you see the addition of functional elements to the l=
anguage as a priori good. I do not see the profit in grafting functional el=
ements into C++.<br></div></div></blockquote><div><br></div><div>First of a=
ll, please understand what a monad is.</div><div>=E2=80=9CMonad=E2=80=9D is=
not a functional programming pattern. </div><div>The monad is a mathe=
matical concept. A very beautiful and simple to understand mathematical con=
cept.</div><div><div>Saying that the monad is a functional programming patt=
ern is like saying that</div><div>eigenvalues are a MATLAB pattern. It=E2=
=80=99s simply wrong.</div><div><br></div></div><div>It is a concept discov=
ered in the =E2=80=9840s, that had nothing to do with programming for decad=
es</div><div>(the same as a lot of other theoretical mathematics that turne=
d out useful later).</div><div>Then it was =E2=80=9Cdiscovered=E2=80=9D in =
the =E2=80=9890s to be useful in computer science because it abstracts a</d=
iv><div>lot of programming patterns. Those programming patterns are not =E2=
=80=9Cfunctional=E2=80=9D. </div><div><br></div><div>Error handling, l=
ogging, Unix pipes, tree and graphs traversals, futures,</div><div>input/ou=
tput, and even nested for loops: all of these very different patterns can b=
e viewed</div><div>as concrete instances of some monad. It=E2=80=99s a univ=
ersal concept, wherever you=E2=80=99re</div><div>programming in assembly or=
in haskell, those patterns _are_ what they are.</div></div></div></blockqu=
ote><div><br>Yes. Those patterns are error handling, logging, Unix pipes, t=
ree and graphs traversals, futures,input/output, and even nested for loops.=
The fact that you can come up with a definition that manages to model all =
of them does not change the fact that <i>they're all different things</i>.<=
br><br>Just because you can group them as though they were all the same doe=
sn't mean you should.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div style=3D"word-wrap:break-word"><div><div>The fact is that functi=
onal programming languages born after the =E2=80=9890s have</div><div>embra=
ced this concept as the basis of portions of their syntax, because</div><di=
v>this was the way of solving a major problem that functional programming</=
div><div>had at the time (how to enforce purity and still be able to do IO)=
..</div><div>That=E2=80=99s why now we associate that concept with functiona=
l programming.</div><div>That=E2=80=99s why I=E2=80=99m citing functional p=
rogramming languages, because they</div><div>have the expertise in which sy=
ntax works better when dealing with</div><div>monadic patterns.</div><div><=
br></div><div>Mind that I=E2=80=99m not saying C++ should embrace all of th=
ose things. For example</div><div>there is no sense in using a monadic nota=
tion to abstract for loops when we</div><div>have, well=E2=80=A6 for loops =
themselves.</div><div><br></div><div>But _if_ we want to understand which a=
re the best ways to</div><div>use expected and optionals, which _are_ monad=
s wherever you call them</div><div>this way or not, and since the language =
currently _does not_ have the right</div><div>syntax for the task, then we =
have to pick up the last 25 years of research</div><div>and study it, not r=
einvent the wheel only because =E2=80=9CC++ is not functional=E2=80=9D.</di=
v></div></div></blockquote><div><br>And therein lies the problem.<br><br>Wh=
at justification do you provide that these objects should be manipulated as=
monads at all?<br><br>After all, you've conceded that "the best way" to ha=
ndle certain monads is to use native syntax for them, rather than some mona=
d thing. So why not do the same things for these objects? Why do you <i>ins=
ist</i> on treating them as monads as a category of entirely dissimilar con=
structs, rather than as individual dissimilar constructs?<br><br>The best w=
ay to use anything is the way that most directly and effectively solves you=
r problem. `optional` is a type that exists to represent an object which ma=
y or may not exist. And thus, the best interface is one that allows you to =
use that concept to solve problems surrounding values that may or may not e=
xists.<br><br>That `optional` <i>just so happens</i> to be able to be class=
ified as a monad is <i>irrelevant</i> to the goal of the class. `optional` =
isn't defined the way it is because it is a monad; that's merely an acciden=
t. The fact that `optional` could be manipluated as a monad does not <i>a p=
riori</i> justify that it <i>should</i> be manipulated in this fashion. Onl=
y a legitimate reason to do so, within the concept of having optional value=
s, would justify such an interface.<br><br>`optional` could "technically" b=
e considered a container too; that doesn't mean we should start getting ite=
rators to an `optional` array.<br><br>And the same goes for `expected`. Thi=
s type exists to represent a means of a function erroring out that has fail=
ed, needs to report that failure, wants to do so to the local caller scope,=
and needs to provide additional information beyond the fact of the failure=
itself.<br><br>Again, the fact that `expected` technically is a monad does=
n't mean squat to this interface. Not unless you can actually justify using=
such an interface to handle it.<br><br>Functional programming <i>needs</i>=
special syntax for monad manipulation. C++ does not; it can get by without=
it. So what is gained by providing such manipulation?<br></div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div>=
<blockquote type=3D"cite"><div dir=3D"ltr"><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>
We don't have lambda expressions because they're useful "in
functional programming"; we have them because it's useful to
be able to, quickly and easily, pass stateful functions to
various APIs in C++. </div>
</div>
</blockquote>
Labmda expressions are useful by them selves. You have the lambda
calculus. This is the base of the functional programming languages.</di=
v></blockquote><div><br>Yes, they are. But as I said, C++ doesn't have them=
<i>for that reason</i>. C++ did not add lambda functions to be the basis o=
f a functional programming model. It added them because they were useful to=
<i>many uses</i> of C++, functional or not.<br><br>So you have to provide =
a reason to do something beyond "that's how functional programming does it"=
or "functional languages have something a lot like that=E2=80=9D.</div></d=
iv></blockquote><div><br></div><div>Nobody has said that the reason is that=
..</div></div></div></blockquote><div><br>You just did. You said very clearl=
y, "we have to pick up the last 25 years of research and study it, not rein=
vent the wheel only because =E2=80=9CC++ is not functional=E2=80=9D." You a=
re justifying adding such an interface because of those "25 years of resear=
ch and study". And where has that been done?<br><br>Functional programming =
languages.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
style=3D"word-wrap:break-word"><div><div>An argument by invocation would b=
e just wrong.</div><div>But the reasons why _they_ have those features rema=
in valid reasons even when you switch</div><div>language.</div></div></div>=
</blockquote><div><br>If that's true, then you ought to be able to explain =
what those reasons are. In terms of C++ code and C++ examples. Without citi=
ng the 25 years of divinely-revealed truth.<br><br>Remember: you're the one=
making the extraordinary claim (C++ needs to have syntactic facilities to =
manipulate monads). So its you who needs to provide the evidence to back it=
up.<br> <br></div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div s=
tyle=3D"word-wrap:break-word"><div><div>If instead you are convinced to be =
talking with radical extremists I don=E2=80=99t understand why you=E2=80=99=
re discussing at all.</div></div></div></blockquote><div><br>I didn't start=
this thread to talk about functional programming. I started it to share my=
ideas and principles when it came to error handling. To explain where thos=
e views came from, and to see what others thought of them. It was the "radi=
cal extremists" who insisted on turning this into a thread about how all er=
ror handling in C++ is irreparably broken, and the one true way to solve it=
is to graft monad operators to C++ and start having every function that ca=
n error return `expected` and for us to litter our code with `await` to han=
dle these errors or other similar syntax.<br><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div><br>=
</div><blockquote type=3D"cite"><div dir=3D"ltr"><blockquote class=3D"gmail=
_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div bgcolor=3D"#FFFFFF" text=3D"#000000"><blockquote type=3D=
"cite"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0=
;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div style=
=3D"word-wrap:break-word"><div><div>Note that expected-style error handling=
also needs
good syntax to be effectively used and not</div>
<div>incur in the same problems: that=E2=80=99s why I advocat=
e it
for C++ only now that we=E2=80=99ll have the monadic</div>
<div>'do notation' provided by the await 2.0 proposal.</div>
</div>
</div>
</blockquote>
<div><br>
What "await 2.0 proposal" are you referring to? What 'do
notation'? I don't see anything like this in N4499.<br>
<br>
Also, something will seriously be wrong in C++ if this becomes
legitimate error handling syntax:<br>
<br>
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><cod=
e>
<div><span style=3D"color:#008">auto</span><span> b </span><s=
pan style=3D"color:#660">=3D</span><span> </span><span style=3D"color:#660"=
>(</span><span>await
</span><span style=3D"color:#660">(</span><span>await a</sp=
an><span style=3D"color:#660">).</span><span>foo</span><span style=3D"color=
:#660">()).</span><span>bar</span><span style=3D"color:#660">();</span></di=
v>
</code></div>
<br>
When I look at this, I see syntax that says "stop here until
this completes", not syntax that says, "handle errors that are
returned by this expression." </div>
</div>
</blockquote>
You should read again the resumable functions proposal.</div></blockquo=
te><div><br><i>Which</i> "resumable functions proposal"? The most recent th=
ing on this subject that I can find (N4499) is pure standardese; trying to =
figure out what the dozens of changes across dozens of chapters actually me=
ans is painful. Even finding out something as simple as what `await` means =
when applied to an expression is byzantine.<br><br>If you're talking about =
N4402, well, that was harder to find, since it's not in <a href=3D"http://w=
ww.open-std.org/JTC1/SC22/WG21/docs/papers/2015/" target=3D"_blank" rel=3D"=
nofollow" onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A=
%2F%2Fwww.open-std.org%2FJTC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2F\46sa\=
75D\46sntz\0751\46usg\75AFQjCNHUqKDS-Ryv0H2zBDFfpohDd9wMtQ';return true;" o=
nclick=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fwww.open-=
std.org%2FJTC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2F\46sa\75D\46sntz\0751=
\46usg\75AFQjCNHUqKDS-Ryv0H2zBDFfpohDd9wMtQ';return true;">the repository</=
a>. I managed to find it<a href=3D"https://isocpp.org/blog/2015/04/n4402" t=
arget=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.g=
oogle.com/url?q\75https%3A%2F%2Fisocpp.org%2Fblog%2F2015%2F04%2Fn4402\46sa\=
75D\46sntz\0751\46usg\75AFQjCNHc4sZJkW5IkiD-BRfKiiAwNZcuNw';return true;" o=
nclick=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fisocpp.=
org%2Fblog%2F2015%2F04%2Fn4402\46sa\75D\46sntz\0751\46usg\75AFQjCNHc4sZJkW5=
IkiD-BRfKiiAwNZcuNw';return true;"> on isocpp.org</a>. I haven't gone throu=
gh it in any detail, but I haven't seen the part that said `await` means er=
ror handling for `expected`.<br><br></div></div></blockquote><div><br></div=
><div>You=E2=80=99re simply not informed so what?</div></div></div></blockq=
uote><div><br>So... inform me. You seem to know what these things are. So g=
ive me a link. Or just explain it here. I clearly looked but didn't find an=
ything particularly enlightening.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_46_1532449897.1433671700950--
------=_Part_45_96815468.1433671700950--
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Sun, 7 Jun 2015 15:23:42 +0200
Raw View
> Il giorno 07/giu/2015, alle ore 12:08, Nicol Bolas <jmckesson@gmail.com> =
ha scritto:
>=20
> On Saturday, June 6, 2015 at 7:20:09 AM UTC-4, Nicola Gigante wrote:
>> Il giorno 06/giu/2015, alle ore 07:40, Nicol Bolas <jmck...@gmail.com> h=
a scritto:
>>=20
>> On Friday, June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Botet Escriba wr=
ote:
>> Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit :
>>> On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigante wrote:
>>>=20
>>> C++ is not a functional language, nor is it going to become one in the =
near future. What happens in "the strongly typed functional programming wor=
ld" is all well and good... for that world. But that alone doesn't make it =
good for C++ or any other world.
>> Why do you say that C++ is not a functional language? C++ is multi-parad=
igm language, imperative, object oriented, functional, ...
>>=20
>> To call something a "functional programming language" requires the inabi=
lity to break the functional paradigm (admittedly, for varying degrees of t=
he word "break"). C++ allows you to restrict yourself, to willingly limit y=
ourself to the functional programming box. What people think of when they s=
ay "functional programming language" doesn't give you the choice; you live =
within the box or write in some other language.
>>=20
>=20
> You misunderstood what functional programming languages are all about.
> There are plenty of functional languages that don=E2=80=99t fulfill your =
definition:
> Common Lisp, Scala, F#, Clojure, Ocaml, Erlang, to name a few.
>=20
> *ahem*: "admittedly, for varying degrees of the word 'break'." That's wha=
t I'm referring to.
>=20
> The fact that these languages let you out of the box sometimes doesn't ch=
ange the fact that the box exists. Your home is still that box.
>=20
sometimes? F# is functional _and_ object oriented (it=E2=80=99s a first-cla=
ss citizen in the .NET world). There=E2=80=99s no box.
> In C++, you don't live in a box. Save for one you construct for yourself.
>=20
That=E2=80=99s why we love this language I suppose.
>=20
>>> You need to justify this with something more than "this is how things w=
ork in functional programming monad pattern matching."
>> The question is, if expected can be seen as a monad, why don't profit fr=
om all the experience other languages have had with this abstraction.
>>=20
>> C++ would only be considered to "profit" from this if you see the additi=
on of functional elements to the language as a priori good. I do not see th=
e profit in grafting functional elements into C++.
>=20
> First of all, please understand what a monad is.
> =E2=80=9CMonad=E2=80=9D is not a functional programming pattern.=20
> The monad is a mathematical concept. A very beautiful and simple to under=
stand mathematical concept.
> Saying that the monad is a functional programming pattern is like saying =
that
> eigenvalues are a MATLAB pattern. It=E2=80=99s simply wrong.
>=20
> It is a concept discovered in the =E2=80=9840s, that had nothing to do wi=
th programming for decades
> (the same as a lot of other theoretical mathematics that turned out usefu=
l later).
> Then it was =E2=80=9Cdiscovered=E2=80=9D in the =E2=80=9890s to be useful=
in computer science because it abstracts a
> lot of programming patterns. Those programming patterns are not =E2=80=9C=
functional=E2=80=9D.=20
>=20
> Error handling, logging, Unix pipes, tree and graphs traversals, futures,
> input/output, and even nested for loops: all of these very different patt=
erns can be viewed
> as concrete instances of some monad. It=E2=80=99s a universal concept, wh=
erever you=E2=80=99re
> programming in assembly or in haskell, those patterns _are_ what they are=
..
>=20
> Yes. Those patterns are error handling, logging, Unix pipes, tree and gra=
phs traversals, futures,input/output, and even nested for loops. The fact t=
hat you can come up with a definition that manages to model all of them doe=
s not change the fact that they're all different things.
>=20
> Just because you can group them as though they were all the same doesn't =
mean you should.
Yes, different things. Or the same up to some isomorphism.
I think the problem here is that we don=E2=80=99t agree on the usefulness o=
f mathematical abstraction
in computer programming (and software engineering).
I=E2=80=99m afraid I cannot convince you in an email.
>=20
> The fact is that functional programming languages born after the =E2=80=
=9890s have
> embraced this concept as the basis of portions of their syntax, because
> this was the way of solving a major problem that functional programming
> had at the time (how to enforce purity and still be able to do IO).
> That=E2=80=99s why now we associate that concept with functional programm=
ing.
> That=E2=80=99s why I=E2=80=99m citing functional programming languages, b=
ecause they
> have the expertise in which syntax works better when dealing with
> monadic patterns.
>=20
> Mind that I=E2=80=99m not saying C++ should embrace all of those things. =
For example
> there is no sense in using a monadic notation to abstract for loops when =
we
> have, well=E2=80=A6 for loops themselves.
>=20
> But _if_ we want to understand which are the best ways to
> use expected and optionals, which _are_ monads wherever you call them
> this way or not, and since the language currently _does not_ have the rig=
ht
> syntax for the task, then we have to pick up the last 25 years of researc=
h
> and study it, not reinvent the wheel only because =E2=80=9CC++ is not fun=
ctional=E2=80=9D.
>=20
> And therein lies the problem.
>=20
> What justification do you provide that these objects should be manipulate=
d as monads at all?
>=20
> After all, you've conceded that "the best way" to handle certain monads i=
s to use native syntax for them, rather than some monad thing. So why not d=
o the same things for these objects? Why do you insist on treating them as =
monads as a category of entirely dissimilar constructs, rather than as indi=
vidual dissimilar constructs?
>=20
Because, as I said, I believe that in contrast to, e.g., for loops, the use=
of optionals and expected values
does not already have a good syntax to handle them.=20
> The best way to use anything is the way that most directly and effectivel=
y solves your problem. `optional` is a type that exists to represent an obj=
ect which may or may not exist. And thus, the best interface is one that al=
lows you to use that concept to solve problems surrounding values that may =
or may not exists.
>=20
> That `optional` just so happens to be able to be classified as a monad is=
irrelevant to the goal of the class. `optional` isn't defined the way it i=
s because it is a monad; that's merely an accident. The fact that `optional=
` could be manipluated as a monad does not a priori justify that it should =
be manipulated in this fashion. Only a legitimate reason to do so, within t=
he concept of having optional values, would justify such an interface.
>=20
That it is merely an accident is true, but where it being merely an acciden=
t is _a good thing_ is another question.
Again, we just disagree on how much mathematics should guide the design of =
the abstractions we use in our code.
> `optional` could "technically" be considered a container too; that doesn'=
t mean we should start getting iterators to an `optional` array.
>=20
I think instead that begin()/end() overloads on optional makes perfect sens=
e in the perspective of generic programming.
> And the same goes for `expected`. This type exists to represent a means o=
f a function erroring out that has failed, needs to report that failure, wa=
nts to do so to the local caller scope, and needs to provide additional inf=
ormation beyond the fact of the failure itself.
>=20
> Again, the fact that `expected` technically is a monad doesn't mean squat=
to this interface. Not unless you can actually justify using such an inter=
face to handle it.
>=20
The justification is easy composition of functions that returns expecteds (=
or optionals, or futures, or ranges, or whatever).
Instead of having to glue up code by pattern matching of if/else or whateve=
r, you just await the function and that=E2=80=99s all.
The primary code execution path is still clean, without syntactic distracti=
ons (besides a single keyword added to the right spot) and
the error is handled correctly and it is _enforced_ by the type system to b=
e handled or explicitly ignored.
> Functional programming needs special syntax for monad manipulation. C++ d=
oes not; it can get by without it. So what is gained by providing such mani=
pulation?
This sentence just does not make sense, sorry.
>>> We don't have lambda expressions because they're useful "in functional =
programming"; we have them because it's useful to be able to, quickly and e=
asily, pass stateful functions to various APIs in C++.
>> Labmda expressions are useful by them selves. You have the lambda calcul=
us. This is the base of the functional programming languages.
>>=20
>> Yes, they are. But as I said, C++ doesn't have them for that reason. C++=
did not add lambda functions to be the basis of a functional programming m=
odel. It added them because they were useful to many uses of C++, functiona=
l or not.
>>=20
>> So you have to provide a reason to do something beyond "that's how funct=
ional programming does it" or "functional languages have something a lot li=
ke that=E2=80=9D.
>=20
> Nobody has said that the reason is that.
>=20
> You just did. You said very clearly, "we have to pick up the last 25 year=
s of research and study it, not reinvent the wheel only because =E2=80=9CC+=
+ is not functional=E2=80=9D." You are justifying adding such an interface =
because of those "25 years of research and study". And where has that been =
done?
>=20
> Functional programming languages.
> =20
> An argument by invocation would be just wrong.
> But the reasons why _they_ have those features remain valid reasons even =
when you switch
> language.
>=20
> If that's true, then you ought to be able to explain what those reasons a=
re. In terms of C++ code and C++ examples. Without citing the 25 years of d=
ivinely-revealed truth.
>=20
> Remember: you're the one making the extraordinary claim (C++ needs to hav=
e syntactic facilities to manipulate monads). So its you who needs to provi=
de the evidence to back it up.
> =20
> If instead you are convinced to be talking with radical extremists I don=
=E2=80=99t understand why you=E2=80=99re discussing at all.
>=20
> I didn't start this thread to talk about functional programming. I starte=
d it to share my ideas and principles when it came to error handling. To ex=
plain where those views came from, and to see what others thought of them. =
It was the "radical extremists" who insisted on turning this into a thread =
about how all error handling in C++ is irreparably broken, and the one true=
way to solve it is to graft monad operators to C++ and start having every =
function that can error return `expected` and for us to litter our code wit=
h `await` to handle these errors or other similar syntax.
>=20
Neither did I. I replied to your original message by arguing what were and =
what weren=E2=80=99t good points in your analysis of the facts.
I cited functional programming languages experience as the source of my opi=
nions, not as the=20
reason why you should believe what I say.
I agreed on some points and disagreed on others. Incidentally your main poi=
nt is one of the ones I agreed upon:
that the standard library (especially Filesystem TS) should provide both AP=
Is (expected based vs throwing).
=20
Then you started to dismiss everything with your =E2=80=9Cstop your functio=
nal propaganda we write C++ not hyppie code=E2=80=9D,
and since what you subsequently said explicitly proved you didn=E2=80=99t h=
ave a clue of what you were saying about
functional languages, I corrected your sentences. But the point is not the =
applicability of functional concepts to C++.
The point is the applicability of _this_ concept to C++ error handling. And=
I and others pointed to our opinions of that already.
If you don=E2=80=99t want to call expected a monad (maybe you may want to c=
all prime numbers =E2=80=9Cdecomposable numbers=E2=80=9D, then),
then I promise you to not use that word anymore.
The usefulness of the abstraction provided by the expected<T> type in conju=
nction with the Awaitable concept
and the await + yield syntax is still there.
>=20
>>> Note that expected-style error handling also needs good syntax to be ef=
fectively used and not
>>> incur in the same problems: that=E2=80=99s why I advocate it for C++ on=
ly now that we=E2=80=99ll have the monadic
>>> 'do notation' provided by the await 2.0 proposal.
>>>=20
>>> What "await 2.0 proposal" are you referring to? What 'do notation'? I d=
on't see anything like this in N4499.
>>>=20
>>> Also, something will seriously be wrong in C++ if this becomes legitima=
te error handling syntax:
>>>=20
>>> auto b =3D (await (await a).foo()).bar();
>>>=20
>>> When I look at this, I see syntax that says "stop here until this compl=
etes", not syntax that says, "handle errors that are returned by this expre=
ssion."
>> You should read again the resumable functions proposal.
>>=20
>> Which "resumable functions proposal"? The most recent thing on this subj=
ect that I can find (N4499) is pure standardese; trying to figure out what =
the dozens of changes across dozens of chapters actually means is painful. =
Even finding out something as simple as what `await` means when applied to =
an expression is byzantine.
>>=20
>> If you're talking about N4402, well, that was harder to find, since it's=
not in the repository. I managed to find it on isocpp.org. I haven't gone =
through it in any detail, but I haven't seen the part that said `await` mea=
ns error handling for `expected`.
>>=20
>=20
> You=E2=80=99re simply not informed so what?
>=20
> So... inform me. You seem to know what these things are. So give me a lin=
k. Or just explain it here. I clearly looked but didn't find anything parti=
cularly enlightening.
>=20
This older document is not =E2=80=9Cstandardese=E2=80=9D and is informative=
enough.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4134.pdf
In N4499, what =E2=80=9Cawait=E2=80=9D applied to an expression means is in=
5.3.8 [expr.await]
Of course it doesn=E2=80=99t directly deal with expected<T>.
Filling a lot of details you can implement the await_suspend() await_resume=
() ecc=E2=80=A6
functions for expected<T> treating it as a always-ready future.
Again, high level that means that the following code:
expected<T,E> func2();
expected<T,E> func() {
T v =3D await func2();
yield v * 2;
}
is roughly equivalent to:
expected<T,E> func2();
expected<T,E> func() {
expected<T,E> e =3D func2();
return e.then([](T v) {
return v * 2;
});
}
Greetings,
Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 07 Jun 2015 17:51:27 +0200
Raw View
This is a multi-part message in MIME format.
--------------090100040609050601010607
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 07/06/15 12:08, Nicol Bolas a =C3=A9crit :
> On Saturday, June 6, 2015 at 7:20:09 AM UTC-4, Nicola Gigante wrote:
>
>> Il giorno 06/giu/2015, alle ore 07:40, Nicol Bolas
>> <jmck...@gmail.com <javascript:>> ha scritto:
>>
>> On Friday, June 5, 2015 at 4:53:15 PM UTC-4, Vicente J. Botet
>> Escriba wrote:
>>
>> Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit :
>>> On Friday, June 5, 2015 at 8:34:24 AM UTC-4, Nicola Gigante
>>> wrote:
>>>
>>> C++ is not a functional language, nor is it going to become
>>> one in the near future. What happens in "the strongly typed
>>> functional programming world" is all well and good... for
>>> that world. But that /alone/ doesn't make it good for C++ or
>>> any other world.
>> Why do you say that C++ is not a functional language? C++ is
>> multi-paradigm language, imperative, object oriented,
>> functional, ...
>>
>>
>> To call something a "functional programming language" requires
>> the inability to break the functional paradigm (admittedly, for
>> varying degrees of the word "break"). C++ allows you to restrict
>> yourself, to willingly limit yourself to the functional
>> programming box. What people think of when they say "functional
>> programming language" doesn't give you the choice; you live
>> within the box or write in some other language.
>>
>
> You misunderstood what functional programming languages are all about=
..
> There are plenty of functional languages that don=E2=80=99t fulfill y=
our
> definition:
> Common Lisp, Scala, F#, Clojure, Ocaml, Erlang, to name a few.
>
>
> *ahem*: "admittedly, for varying degrees of the word 'break'." That's=20
> what I'm referring to.
>
> The fact that these languages let you out of the box sometimes doesn't=20
> change the fact that the box exists. Your home is still that box.
>
> In C++, you don't live in a box. Save for one you construct for yourself.
>
>
>>> You need to justify this with something more than "this is
>>> how things work in functional programming monad pattern
>>> matching."
>> The question is, if expected can be seen as a monad, why
>> don't profit from all the experience other languages have had
>> with this abstraction.
>>
>>
>> C++ would only be considered to "profit" from this if you see the
>> addition of functional elements to the language as a priori good.
>> I do not see the profit in grafting functional elements into C++.
>
> First of all, please understand what a monad is.
> =E2=80=9CMonad=E2=80=9D is not a functional programming pattern.
> The monad is a mathematical concept. A very beautiful and simple
> to understand mathematical concept.
> Saying that the monad is a functional programming pattern is like
> saying that
> eigenvalues are a MATLAB pattern. It=E2=80=99s simply wrong.
>
> It is a concept discovered in the =E2=80=9840s, that had nothing to d=
o
> with programming for decades
> (the same as a lot of other theoretical mathematics that turned
> out useful later).
> Then it was =E2=80=9Cdiscovered=E2=80=9D in the =E2=80=9890s to be us=
eful in computer
> science because it abstracts a
> lot of programming patterns. Those programming patterns are not
> =E2=80=9Cfunctional=E2=80=9D.
>
> Error handling, logging, Unix pipes, tree and graphs traversals,
> futures,
> input/output, and even nested for loops: all of these very
> different patterns can be viewed
> as concrete instances of some monad. It=E2=80=99s a universal concept=
,
> wherever you=E2=80=99re
> programming in assembly or in haskell, those patterns _are_ what
> they are.
>
>
> Yes. Those patterns are error handling, logging, Unix pipes, tree and=20
> graphs traversals, futures,input/output, and even nested for loops.=20
> The fact that you can come up with a definition that manages to model=20
> all of them does not change the fact that /they're all different things/.
>
> Just because you can group them as though they were all the same=20
> doesn't mean you should.
Remember Programs =3D Data + Algorithms
All these concrete examples are Data that share a lot of Algorithms=20
because they can be seen as a Monad.
Do you recognize the STL design here? Concepts, algorithms, ....
>
> The fact is that functional programming languages born after the
> =E2=80=9890s have
> embraced this concept as the basis of portions of their syntax,
> because
> this was the way of solving a major problem that functional
> programming
> had at the time (how to enforce purity and still be able to do IO).
> That=E2=80=99s why now we associate that concept with functional prog=
ramming.
> That=E2=80=99s why I=E2=80=99m citing functional programming language=
s, because they
> have the expertise in which syntax works better when dealing with
> monadic patterns.
>
> Mind that I=E2=80=99m not saying C++ should embrace all of those thin=
gs.
> For example
> there is no sense in using a monadic notation to abstract for
> loops when we
> have, well=E2=80=A6 for loops themselves.
>
> But _if_ we want to understand which are the best ways to
> use expected and optionals, which _are_ monads wherever you call them
> this way or not, and since the language currently _does not_ have
> the right
> syntax for the task, then we have to pick up the last 25 years of
> research
> and study it, not reinvent the wheel only because =E2=80=9CC++ is not
> functional=E2=80=9D.
>
>
> And therein lies the problem.
>
> What justification do you provide that these objects should be=20
> manipulated as monads at all?
>
> After all, you've conceded that "the best way" to handle certain=20
> monads is to use native syntax for them, rather than some monad thing.=20
> So why not do the same things for these objects? Why do you /insist/=20
> on treating them as monads as a category of entirely dissimilar=20
> constructs, rather than as individual dissimilar constructs?
>
> The best way to use anything is the way that most directly and=20
> effectively solves your problem. `optional` is a type that exists to=20
> represent an object which may or may not exist. And thus, the best=20
> interface is one that allows you to use that concept to solve problems=20
> surrounding values that may or may not exists.
>
> That `optional` /just so happens/ to be able to be classified as a=20
> monad is /irrelevant/ to the goal of the class. `optional` isn't=20
> defined the way it is because it is a monad; that's merely an=20
> accident. The fact that `optional` could be manipluated as a monad=20
> does not /a priori/ justify that it /should/ be manipulated in this=20
> fashion. Only a legitimate reason to do so, within the concept of=20
> having optional values, would justify such an interface.
>
> `optional` could "technically" be considered a container too; that=20
> doesn't mean we should start getting iterators to an `optional` array.
>
> And the same goes for `expected`. This type exists to represent a=20
> means of a function erroring out that has failed, needs to report that=20
> failure, wants to do so to the local caller scope, and needs to=20
> provide additional information beyond the fact of the failure itself.
>
> Again, the fact that `expected` technically is a monad doesn't mean=20
> squat to this interface. Not unless you can actually justify using=20
> such an interface to handle it.
>
Don't all containers share some common functions so that we are able to=20
define algorithms that wroks for all of them ?
> Functional programming /needs/ special syntax for monad manipulation.=20
> C++ does not; it can get by without it. So what is gained by providing=20
> such manipulation?
>
>>> We don't have lambda expressions because they're useful "in
>>> functional programming"; we have them because it's useful to
>>> be able to, quickly and easily, pass stateful functions to
>>> various APIs in C++.
>> Labmda expressions are useful by them selves. You have the
>> lambda calculus. This is the base of the functional
>> programming languages.
>>
>>
>> Yes, they are. But as I said, C++ doesn't have them /for that
>> reason/. C++ did not add lambda functions to be the basis of a
>> functional programming model. It added them because they were
>> useful to /many uses/ of C++, functional or not.
>>
>> So you have to provide a reason to do something beyond "that's
>> how functional programming does it" or "functional languages have
>> something a lot like that=E2=80=9D.
>
> Nobody has said that the reason is that.
>
>
> You just did. You said very clearly, "we have to pick up the last 25=20
> years of research and study it, not reinvent the wheel only because=20
> =E2=80=9CC++ is not functional=E2=80=9D." You are justifying adding such =
an interface=20
> because of those "25 years of research and study". And where has that=20
> been done?
>
There is no reason to don't profit from this experience as you seems to=20
intend just because C++ is different.
> Functional programming languages.
>
> An argument by invocation would be just wrong.
> But the reasons why _they_ have those features remain valid
> reasons even when you switch
> language.
>
>
> If that's true, then you ought to be able to explain what those=20
> reasons are. In terms of C++ code and C++ examples. Without citing the=20
> 25 years of divinely-revealed truth.
>
> Remember: you're the one making the extraordinary claim (C++ needs to=20
> have syntactic facilities to manipulate monads). So its you who needs=20
> to provide the evidence to back it up.
The facilities are already proposed by others. Are you against this=20
facilities?
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------090100040609050601010607
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 07/06/15 12:08, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:33bf1010-4067-402a-a025-b1ed10d15707@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Saturday, June 6, 2015 at 7:20:09 AM UTC-4,
Nicola Gigante wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>
<blockquote type=3D"cite">
<div>Il giorno 06/giu/2015, alle ore 07:40, Nicol Bolas
<<a moz-do-not-send=3D"true" href=3D"javascript:"
target=3D"_blank" gdf-obfuscated-mailto=3D"00ZdmC7KsPYJ=
"
rel=3D"nofollow"
onmousedown=3D"this.href=3D'javascript:';return true;"
onclick=3D"this.href=3D'javascript:';return true;">jmck=
....@gmail.com</a>>
ha scritto:</div>
<br>
<div>
<div dir=3D"ltr">On Friday, June 5, 2015 at 4:53:15 PM
UTC-4, Vicente J. Botet Escriba wrote:
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px
#ccc solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 18:36, Nicol Bolas a =C3=A9crit=C2=
=A0:<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at
8:34:24 AM UTC-4, Nicola Gigante wrote:<br>
<div><br>
C++ is not a functional language, nor is
it going to become one in the near future.
What happens in "the strongly typed
functional programming world" is all well
and good... for that world. But that <i>alone=
</i>
doesn't make it good for C++ or any other
world.<br>
</div>
</div>
</blockquote>
Why do you say that C++ is not a functional
language? C++ is multi-paradigm language,
imperative, object oriented, functional, ...<br>
</div>
</blockquote>
<div><br>
To call something a "functional programming
language" requires the inability to break the
functional paradigm (admittedly, for varying
degrees of the word "break"). C++ allows you to
restrict yourself, to willingly limit yourself to
the functional programming box. What people think
of when they say "functional programming language"
doesn't give you the choice; you live within the
box or write in some other language.<br>
<br>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>You misunderstood what functional programming
languages are all about.</div>
<div>There are plenty of functional languages that don=E2=80=
=99t
fulfill your definition:</div>
<div>Common Lisp, Scala, F#, Clojure, Ocaml, Erlang, to
name a few.</div>
</div>
</div>
</blockquote>
<div><br>
*ahem*: "admittedly, for varying degrees of the word 'break'."
That's what I'm referring to.<br>
<br>
The fact that these languages let you out of the box sometimes
doesn't change the fact that the box exists. Your home is
still that box.<br>
<br>
In C++, you don't live in a box. Save for one you construct
for yourself.<br>
<br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div><br>
</div>
<div>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px
#ccc solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> You need to justify this with something
more than "this is how things work in
functional programming monad pattern
matching."<br>
</div>
</div>
</blockquote>
The question is, if expected can be seen as a
monad, why don't profit from all the experience
other languages have had with this abstraction.</div>
</blockquote>
<div><br>
C++ would only be considered to "profit" from this
if you see the addition of functional elements to
the language as a priori good. I do not see the
profit in grafting functional elements into C++.<br>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>First of all, please understand what a monad is.</div>
<div>=E2=80=9CMonad=E2=80=9D is not a functional programming =
pattern.=C2=A0</div>
<div>The monad is a mathematical concept. A very beautiful
and simple to understand mathematical concept.</div>
<div>
<div>Saying that the monad is a functional programming
pattern is like saying that</div>
<div>eigenvalues are a MATLAB pattern. It=E2=80=99s simply
wrong.</div>
<div><br>
</div>
</div>
<div>It is a concept discovered in the =E2=80=9840s, that had
nothing to do with programming for decades</div>
<div>(the same as a lot of other theoretical mathematics
that turned out useful later).</div>
<div>Then it was =E2=80=9Cdiscovered=E2=80=9D in the =E2=80=
=9890s to be useful in
computer science because it abstracts a</div>
<div>lot of programming patterns. Those programming
patterns are not =E2=80=9Cfunctional=E2=80=9D.=C2=A0</div>
<div><br>
</div>
<div>Error handling, logging, Unix pipes, tree and graphs
traversals, futures,</div>
<div>input/output, and even nested for loops: all of these
very different patterns can be viewed</div>
<div>as concrete instances of some monad. It=E2=80=99s a univ=
ersal
concept, wherever you=E2=80=99re</div>
<div>programming in assembly or in haskell, those patterns
_are_ what they are.</div>
</div>
</div>
</blockquote>
<div><br>
Yes. Those patterns are error handling, logging, Unix pipes,
tree and graphs traversals, futures,input/output, and even
nested for loops. The fact that you can come up with a
definition that manages to model all of them does not change
the fact that <i>they're all different things</i>.<br>
<br>
Just because you can group them as though they were all the
same doesn't mean you should.<br>
</div>
</div>
</blockquote>
Remember Programs =3D Data + Algorithms<br>
<br>
All these concrete examples are Data that share a lot of Algorithms
because they can be seen as a Monad.<br>
Do you recognize the STL design here? Concepts, algorithms, ....<br>
<blockquote
cite=3D"mid:33bf1010-4067-402a-a025-b1ed10d15707@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>
<div>The fact is that functional programming languages
born after the =E2=80=9890s have</div>
<div>embraced this concept as the basis of portions of
their syntax, because</div>
<div>this was the way of solving a major problem that
functional programming</div>
<div>had at the time (how to enforce purity and still be
able to do IO).</div>
<div>That=E2=80=99s why now we associate that concept with
functional programming.</div>
<div>That=E2=80=99s why I=E2=80=99m citing functional program=
ming
languages, because they</div>
<div>have the expertise in which syntax works better when
dealing with</div>
<div>monadic patterns.</div>
<div><br>
</div>
<div>Mind that I=E2=80=99m not saying C++ should embrace all =
of
those things. For example</div>
<div>there is no sense in using a monadic notation to
abstract for loops when we</div>
<div>have, well=E2=80=A6 for loops themselves.</div>
<div><br>
</div>
<div>But _if_ we want to understand which are the best
ways to</div>
<div>use expected and optionals, which _are_ monads
wherever you call them</div>
<div>this way or not, and since the language currently
_does not_ have the right</div>
<div>syntax for the task, then we have to pick up the last
25 years of research</div>
<div>and study it, not reinvent the wheel only because
=E2=80=9CC++ is not functional=E2=80=9D.</div>
</div>
</div>
</blockquote>
<div><br>
And therein lies the problem.<br>
<br>
What justification do you provide that these objects should be
manipulated as monads at all?<br>
<br>
After all, you've conceded that "the best way" to handle
certain monads is to use native syntax for them, rather than
some monad thing. So why not do the same things for these
objects? Why do you <i>insist</i> on treating them as monads
as a category of entirely dissimilar constructs, rather than
as individual dissimilar constructs?<br>
<br>
The best way to use anything is the way that most directly and
effectively solves your problem. `optional` is a type that
exists to represent an object which may or may not exist. And
thus, the best interface is one that allows you to use that
concept to solve problems surrounding values that may or may
not exists.<br>
<br>
That `optional` <i>just so happens</i> to be able to be
classified as a monad is <i>irrelevant</i> to the goal of the
class. `optional` isn't defined the way it is because it is a
monad; that's merely an accident. The fact that `optional`
could be manipluated as a monad does not <i>a priori</i>
justify that it <i>should</i> be manipulated in this fashion.
Only a legitimate reason to do so, within the concept of
having optional values, would justify such an interface.<br>
<br>
`optional` could "technically" be considered a container too;
that doesn't mean we should start getting iterators to an
`optional` array.<br>
<br>
And the same goes for `expected`. This type exists to
represent a means of a function erroring out that has failed,
needs to report that failure, wants to do so to the local
caller scope, and needs to provide additional information
beyond the fact of the failure itself.<br>
<br>
Again, the fact that `expected` technically is a monad doesn't
mean squat to this interface. Not unless you can actually
justify using such an interface to handle it.<br>
<br>
</div>
</div>
</blockquote>
Don't all containers share some common functions so that we are able
to define algorithms that wroks for all of them ?<br>
<blockquote
cite=3D"mid:33bf1010-4067-402a-a025-b1ed10d15707@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>Functional programming <i>needs</i> special syntax for
monad manipulation. C++ does not; it can get by without it. So
what is gained by providing such manipulation?<br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px
#ccc solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> We don't have lambda expressions because
they're useful "in functional programming";
we have them because it's useful to be able
to, quickly and easily, pass stateful
functions to various APIs in C++. </div>
</div>
</blockquote>
Labmda expressions are useful by them selves. You
have the lambda calculus. This is the base of the
functional programming languages.</div>
</blockquote>
<div><br>
Yes, they are. But as I said, C++ doesn't have them
<i>for that reason</i>. C++ did not add lambda
functions to be the basis of a functional
programming model. It added them because they were
useful to <i>many uses</i> of C++, functional or
not.<br>
<br>
So you have to provide a reason to do something
beyond "that's how functional programming does it"
or "functional languages have something a lot like
that=E2=80=9D.</div>
</div>
</blockquote>
<div><br>
</div>
<div>Nobody has said that the reason is that.</div>
</div>
</div>
</blockquote>
<div><br>
You just did. You said very clearly, "we have to pick up the
last 25 years of research and study it, not reinvent the wheel
only because =E2=80=9CC++ is not functional=E2=80=9D." You are ju=
stifying
adding such an interface because of those "25 years of
research and study". And where has that been done?<br>
<br>
</div>
</div>
</blockquote>
There is no reason to don't profit from this experience as you seems
to intend just because C++ is different.<br>
<blockquote
cite=3D"mid:33bf1010-4067-402a-a025-b1ed10d15707@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>Functional programming languages.<br>
=C2=A0</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>
<div>An argument by invocation would be just wrong.</div>
<div>But the reasons why _they_ have those features remain
valid reasons even when you switch</div>
<div>language.</div>
</div>
</div>
</blockquote>
<div><br>
If that's true, then you ought to be able to explain what
those reasons are. In terms of C++ code and C++ examples.
Without citing the 25 years of divinely-revealed truth.<br>
<br>
Remember: you're the one making the extraordinary claim (C++
needs to have syntactic facilities to manipulate monads). So
its you who needs to provide the evidence to back it up.<br>
</div>
</div>
</blockquote>
The facilities are already proposed by others. Are you against this
facilities?<br>
<br>
Vicente<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------090100040609050601010607--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 07 Jun 2015 18:02:16 +0200
Raw View
This is a multi-part message in MIME format.
--------------090109080701070705070605
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 07/06/15 09:48, Nicol Bolas a =C3=A9crit :
> On Saturday, June 6, 2015 at 7:04:02 AM UTC-4, Vicente J. Botet=20
> Escriba wrote:
>
> Le 06/06/15 09:24, Nicol Bolas a =C3=A9crit :
>> On Saturday, June 6, 2015 at 3:08:28 AM UTC-4, Vicente J. Botet
>> Escriba wrote:
>>
>> Le 05/06/15 20:13, Nicol Bolas a =C3=A9crit :
>>> On Friday, June 5, 2015 at 1:40:33 PM UTC-4, Matthew Woehlke
>>> wrote:
>>
>>> Why not? future<T> behaves this way. Moving from a function
>>> that returns expected<T> to a function that returns
>>> future<T> will have not too much consequences on the caller
>>> side (if we reach to remove the syntactical differences -
>>> get versus value - or if we provide a monadic interface and
>>> both classes are mapped to model this concept).
>>
>>
>> `std::future` throws whatever exception was set into the
>> `promise` it is attached to. The equivalent in `expected` would
>> be `exception_ptr`.
>>
>> And the consequences of using `exception_ptr` in `expected` are
>> pretty substantial. The code looking at the `expected` can't tell
>> anything useful about the nature of the error; all it knows is
>> that some kind of error took place.
>>
> Why?
>
>
> Have you actually looked at what is laughably called the interface to=20
> `exception_ptr`=20
> <http://en.cppreference.com/w/cpp/error/exception_ptr>? Outside of=20
> pointer-like behavior, there is only one thing you can do with one:=20
> throw it.
>
> That's it.
>
> So explain how a user could possibly learn anything about the nature=20
> of an exception from that. Without actually throwing it, of course.
>
I surely missunderstood what you meant. Anyway, this is no difference in=20
this subject for functions returning expected<T> or future<T>.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------090109080701070705070605
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 07/06/15 09:48, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:b2a1d0d7-f2f2-4e7b-99ec-620b1637e3f6@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Saturday, June 6, 2015 at 7:04:02 AM UTC-4,
Vicente J. Botet Escriba wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 06/06/15 09:24, Nicol Bolas a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Saturday, June 6, 2015 at 3:08:28 AM
UTC-4, Vicente J. Botet Escriba wrote:
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 05/06/15 20:13, Nicol Bolas a =C3=A9crit=C2=A0:=
<br>
</div>
<blockquote type=3D"cite">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">On Friday,
June 5, 2015 at 1:40:33 PM UTC-4, Matthew
Woehlke wrote:</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">Why not?
future<T> behaves this way. Moving from a
function that returns expected<T> to a
function that returns future<T> will have
not too much consequences on the caller side (if
we reach to remove the syntactical differences -
get versus value - or if we provide a monadic
interface and both classes are mapped to model
this concept).<br>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex"> </blockquote>
<div><br>
`std::future` throws whatever exception was set into
the `promise` it is attached to. The equivalent in
`expected` would be `exception_ptr`.<br>
<br>
And the consequences of using `exception_ptr` in
`expected` are pretty substantial. The code looking at
the `expected` can't tell anything useful about the
nature of the error; all it knows is that some kind of
error took place.<br>
</div>
</div>
<br>
</blockquote>
Why?<br>
</div>
</blockquote>
<div><br>
Have you actually <a moz-do-not-send=3D"true"
href=3D"http://en.cppreference.com/w/cpp/error/exception_ptr">l=
ooked
at what is laughably called the interface to `exception_ptr`</a=
>?
Outside of pointer-like behavior, there is only one thing you
can do with one: throw it.<br>
<br>
That's it.<br>
<br>
So explain how a user could possibly learn anything about the
nature of an exception from that. Without actually throwing
it, of course.<br>
</div>
</div>
<br>
</blockquote>
I surely missunderstood what you meant. Anyway, this is no
difference in this subject for functions returning expected<T>
or future<T>. <br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------090109080701070705070605--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 07 Jun 2015 18:17:55 +0200
Raw View
This is a multi-part message in MIME format.
--------------050308080408020908050804
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 07/06/15 09:40, Nicol Bolas a =C3=A9crit :
>
>
> On Saturday, June 6, 2015 at 7:00:03 AM UTC-4, Vicente J. Botet=20
> Escriba wrote:
>
> Le 06/06/15 09:19, Nicol Bolas a =C3=A9crit :
>> On Friday, June 5, 2015 at 6:42:30 PM UTC-4, Matthew Woehlke wrote:
>>
>> On 2015-06-05 17:34, Vicente J. Botet Escriba wrote:
>> > Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit :
>> >> OK, so... what about static analysis tools? We already
>> have great
>> >> static tools that can detect the use of many uninitialized
>> values.
>> >
>> > expected as optional, and I hope would variant, are never
>> uninitialized
>> > as these classes have default constructor.
>>
>> Not the expected/optional itself, but the contained value.
>>
>> IOW, this is a (potential) error:
>>
>> auto x =3D function_that_returns_expected_or_optional;
>> do_something(x.value());
>>
>> ...because you didn't check that 'x' actually *has* a value,
>> and thus
>> value() might throw.
>>
>> Nicol is of the opinion that one should never write code like
>> this, even
>> if throwing from the context where value() is called if there
>> is no
>> value is the intended behavior.
>>
>> I have to ask, though: in that case, why throw at all?
>>
>>
>> Because "wrong" doesn't necessarily mean "shouldn't be allowed."
>>
>> Sometimes, some piece of code winds up with an `expected` that
>> doesn't have its value, and that code's precondition is that it
>> should have a value. The code doesn't check it because it
>> shouldn't be possible, but maybe they've done something that
>> defeats the static analysis tool (or their compiler isn't smart
>> enough to find it for them). But for whatever reason, this code
>> bug has happened.
>>
> if there is a precondition that there is a value, the function
> should take a T as parameter not an expected<T>.
>
>
> You're assuming it's a "function" rather than just "code".
Could you show me an example where there is a precondition an expected=20
has a value?
> A particular piece of code has preconditions too, things that it=20
> assumes have happened, so it doesn't check for them.
The use of value() has not preconditions so there is nothing to assume.
>
>> Really, I envision expected as a 'delayed throw' mechanism.
>> The point is
>> to return an expected instead of throwing immediately, and
>> instead delay
>> *the throw that otherwise would have happened* until the user
>> calls
>> value(), thus giving a window where the user can choose to
>> handle the
>> error before an exception is thrown.
>>
>>
>> Well, a lot of the functional programming crowd in this thread
>> seems to think that `expected` objects should be flying up the
>> call-stack via `await` shenanigans or whatever. So there's some
>> disagreement here as to how `expected` ought to be used.
>>
> Why you want to tell to the user how it must use expected? This is
> not up to the standard.
>
>
> Of course it is. It's a decision of the standard to allow `value` to=20
> throw at all. Therefore, the standard says how you can use `value`.
Are you saying that you don't want value() to throw if there is not a=20
value()? Or that you don't want await to be applicable to expected, or=20
what ?
>
> People are suggesting that `await` should be grafted onto `expected`=20
> as well. Others are suggesting some "pattern matching" syntax or some=20
> such. These are all very much ways the standard tells users how a type=20
> may be used.
>
>> I see `expected` as how I described it in my look at it: an
>> alternate way to pass an error directly to the local calling scope.
>>
>> There are several problems with thinking of `expected` as merely
>> a delayed throwing mechanic. Part of it has to do with what goes
>> into the error code portion.
>>
>> As previously stated, exceptions often need rich information,
>> since they are usually processed far from their invocation site.
>> `expected` objects are usually processed close enough that the
>> local code can get much of this information themselves. In those
>> cases, a simple std::error_condition is often sufficient.
>>
>> Something like `exception_ptr` is completely opaque; the only
>> thing you can do with that is throw it. You can't inspect it to
>> find out which exception was captured or anything. Even a shared
>> pointer to some object is problematic because you're having to
>> allocate memory just to pass an error.
> std::variant is an valid alternative. It is equivalent to
> exception specifications. I prefer yet std::any that as the ABI
> don't changes when new errors are added. Neither of them forces an
> allocation.
>
>
> std::any very much does do memory allocation. Oh, implementations may=20
> have some small-object-optimization in its storage. But that's a QOI=20
> issue; just read the spec=20
> <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4480.html#any.c=
lass>.=20
> Implementations "should avoid the use of dynamically allocated memory=20
> for a small contained object". How big "small" is is a QOI issue. And=20
> since we're talking about arbitrary objects, you can't guarantee that.
When the object are big enough I could live with it been on the heap, yes.
You can even has variant<E1, ... EN, any>
Here you are saying that you want these Ei error to be stored on the=20
stack and others possibly on the heap.
A specific class any_or<E1, ... EN> could implement better this pattern=20
as it know the size taken by the Ei so any other error with smaller size=20
could use this storage.
Vicente
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------050308080408020908050804
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 07/06/15 09:40, Nicol Bolas a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:ed85c204-59d4-432e-a35b-8a0dba24d083@isocpp.org"
type=3D"cite">
<div dir=3D"ltr"><br>
<br>
On Saturday, June 6, 2015 at 7:00:03 AM UTC-4, Vicente J. Botet
Escriba wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 06/06/15 09:19, Nicol Bolas a =C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, June 5, 2015 at 6:42:30 PM
UTC-4, Matthew Woehlke wrote:
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex">On 2015-06-05 17:34, Vicente
J. Botet Escriba wrote: <br>
> Le 05/06/15 21:19, Nicol Bolas a =C3=A9crit : <br>
>> OK, so... what about static analysis tools?
We already have great <br>
>> static tools that can detect the use of many
uninitialized values. <br>
> <br>
> expected as optional, and I hope would variant,
are never uninitialized <br>
> as these classes have default constructor. <br>
<br>
Not the expected/optional itself, but the contained
value. <br>
<br>
IOW, this is a (potential) error: <br>
<br>
=C2=A0 auto x =3D function_that_returns_<wbr>expected_or_=
optional;
<br>
=C2=A0 do_something(x.value()); <br>
<br>
...because you didn't check that 'x' actually *has* a
value, and thus <br>
value() might throw. <br>
<br>
Nicol is of the opinion that one should never write
code like this, even <br>
if throwing from the context where value() is called
if there is no <br>
value is the intended behavior. <br>
<br>
I have to ask, though: in that case, why throw at all?<br=
>
</blockquote>
<div><br>
Because "wrong" doesn't necessarily mean "shouldn't be
allowed."<br>
<br>
Sometimes, some piece of code winds up with an
`expected` that doesn't have its value, and that
code's precondition is that it should have a value.
The code doesn't check it because it shouldn't be
possible, but maybe they've done something that
defeats the static analysis tool (or their compiler
isn't smart enough to find it for them). But for
whatever reason, this code bug has happened.<br>
<br>
</div>
</div>
</blockquote>
if there is a precondition that there is a value, the
function should take a T as parameter not an
expected<T>.<br>
</div>
</blockquote>
<div><br>
You're assuming it's a "function" rather than just "code". </div>
</div>
</blockquote>
Could you show me an example where there is a precondition an
expected has a value? <br>
<blockquote
cite=3D"mid:ed85c204-59d4-432e-a35b-8a0dba24d083@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>A particular piece of code has preconditions too, things
that it assumes have happened, so it doesn't check for them.<br>
</div>
</div>
</blockquote>
The use of value() has not preconditions so there is nothing to
assume.<br>
<blockquote
cite=3D"mid:ed85c204-59d4-432e-a35b-8a0dba24d083@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div> </div>
<blockquote class=3D"gmail_quote"
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc
solid;padding-left:1ex"> Really, I envision expected
as a 'delayed throw' mechanism. The point is <br>
to return an expected instead of throwing immediately,
and instead delay <br>
*the throw that otherwise would have happened* until
the user calls <br>
value(), thus giving a window where the user can
choose to handle the <br>
error before an exception is thrown.<br>
</blockquote>
<div><br>
Well, a lot of the functional programming crowd in
this thread seems to think that `expected` objects
should be flying up the call-stack via `await`
shenanigans or whatever. So there's some disagreement
here as to how `expected` ought to be used.<br>
<br>
</div>
</div>
</blockquote>
Why you want to tell to the user how it must use expected?
This is not up to the standard.<br>
</div>
</blockquote>
<div><br>
Of course it is. It's a decision of the standard to allow
`value` to throw at all. Therefore, the standard says how you
can use `value`.<br>
</div>
</div>
</blockquote>
Are you saying that you don't want value() to throw if there is not
a value()? Or that you don't want await to be applicable to
expected, or what ?<br>
<blockquote
cite=3D"mid:ed85c204-59d4-432e-a35b-8a0dba24d083@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><br>
People are suggesting that `await` should be grafted onto
`expected` as well. Others are suggesting some "pattern
matching" syntax or some such. These are all very much ways
the standard tells users how a type may be used.<br>
=C2=A0</div>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div>I see `expected` as how I described it in my look
at it: an alternate way to pass an error directly to
the local calling scope.<br>
<br>
There are several problems with thinking of `expected`
as merely a delayed throwing mechanic. Part of it has
to do with what goes into the error code portion.<br>
<br>
As previously stated, exceptions often need rich
information, since they are usually processed far from
their invocation site. `expected` objects are usually
processed close enough that the local code can get
much of this information themselves. In those cases, a
simple std::error_condition is often sufficient.<br>
<br>
Something like `exception_ptr` is completely opaque;
the only thing you can do with that is throw it. You
can't inspect it to find out which exception was
captured or anything. Even a shared pointer to some
object is problematic because you're having to
allocate memory just to pass an error.<br>
</div>
</div>
</blockquote>
std::variant is an valid alternative. It is equivalent to
exception specifications. I prefer yet std::any that as the
ABI don't changes when new errors are added. Neither of them
forces an allocation.<br>
</div>
</blockquote>
<div><br>
std::any very much does do memory allocation. Oh,
implementations may have some small-object-optimization in its
storage. But that's a QOI issue; just <a
moz-do-not-send=3D"true"
href=3D"http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4480.html#=
any.class">read
the spec</a>. Implementations "should avoid the use of
dynamically allocated memory for a small contained object".
How big "small" is is a QOI issue. And since we're talking
about arbitrary objects, you can't guarantee that.<br>
</div>
</div>
</blockquote>
When the object are big enough I could live with it been on the
heap, yes. <br>
<br>
You can even has variant<E1, ... EN, any><br>
<br>
Here you are saying that you want these Ei error to be stored on the
stack and others possibly on the heap.<br>
<br>
A specific class any_or<E1, ... EN> could implement better
this pattern as it know the size taken by the Ei so any other error
with smaller size could use this storage.<br>
<br>
Vicente <br>
<br>
<br>
<br>
Vicente <br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------050308080408020908050804--
.
Author: Matthew Woehlke <mw_triad@users.sourceforge.net>
Date: Tue, 09 Jun 2015 07:50:32 -0400
Raw View
On 2015-06-06 03:24, Nicol Bolas wrote:
> And the consequences of using `exception_ptr` in `expected` are pretty
> substantial. The code looking at the `expected` can't tell anything useful
> about the nature of the error; all it knows is that some kind of error took
> place.
Okay, I don't get this... if this is the case, how is the exception *in
any way* useful? I.e. why does exception_ptr ever exist?
Presumably you could differentiate it by actually throwing it and
catching it, could you not? And if you can do that, why can't you do the
same thing *without throwing it first*?
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Tue, 9 Jun 2015 08:36:11 -0700 (PDT)
Raw View
------=_Part_508_1040098230.1433864171295
Content-Type: multipart/alternative;
boundary="----=_Part_509_1343942930.1433864171295"
------=_Part_509_1343942930.1433864171295
Content-Type: text/plain; charset=UTF-8
On Sunday, June 7, 2015 at 2:23:50 PM UTC+1, Nicola Gigante wrote:
>
> [...]
>
> Again, high level that means that the following code:
>
> expected<T,E> func2();
> expected<T,E> func() {
> T v = await func2();
>
> yield v * 2;
> }
>
> is roughly equivalent to:
>
> expected<T,E> func2();
> expected<T,E> func() {
> expected<T,E> e = func2();
>
> return e.then([](T v) {
> return v * 2;
> });
> }
>
>
Cool. Christopher Kohlhoff and Oliver Kowalke proposed a coroutine variant
which would infer await, so the example would become (IIRC):
expected<T,E> func2();
expected<T,E> func() {
T v = func2();
return v * 2;
}
also expected is such a fundamental concept that we might want to add
language support for it, something like:
T func2() expected(E);
T func() expected(E) {
T v = func2();
yield v*2;
}
Of course syntatic sugar for calling catch_error might also be useful:
T func2() expected(E);
T func() expected(E) {
do_try {
T v = func2();
yield v*2;
} catch_error(E e)
{
// log e
raise e;
}
}
What, that reminds me of something....
With enough syntatic sugar, exceptions and expected are semantically
equivalent, with the notable difference that the expected error type is
statically checked (but then again you can have except<T, std::any> ). The
biggest difference is in the preferred implementation: an explicit CSP
transformation with yield/await and non local jumps for exceptions, but
either feature could be implemented with either strategy.
I do like 'expected' and the fact that the coroutine proposals work as
monadic do notation is great, but given the history behind C++ we are
probably better of with:
* an attribute to ask the compiler to make different trade-off between the
normal and exceptional case.
* the addition of optional static exception checking which would close the
last gap between exceptions and expected. Static exceptions types are
considered a failure in Java, but I believe that parametric exception
specifications and possibly inference a-la 'throw(auto)' would remove most
of the complains of exception specifications. And anyway expected is really
equivalent to them.
-- gpd
> Greetings,
> Nicola
>
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_509_1343942930.1433864171295
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, June 7, 2015 at 2:23:50 PM UTC+1, Nicola Gigant=
e wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
[...]<br><br>Again, high level that means that the following code:
<br>
<br>expected<T,E> func2();
<br>expected<T,E> func() {
<br> T v =3D await func2();
<br>
<br> yield v * 2;
<br>}
<br>
<br>is roughly equivalent to:
<br>
<br>expected<T,E> func2();
<br>expected<T,E> func() {
<br> expected<T,E> e =3D func2();
<br>
<br> return e.then([](T v) {
<br> return v * 2;
<br> });
<br>}
<br>
<br></blockquote><div><br>Cool. Christopher Kohlhoff and Oliver Kowalke pr=
oposed a coroutine variant which would infer await, so the example would be=
come (IIRC):<br> <br>expected<T,E> func2();
<br>expected<T,E> func() {
<br> T v =3D func2();
<br>
<br> return v * 2;
<br>}
<br>
<br>also expected is such a fundamental concept that we might want to add l=
anguage support for it, something like:<br><br>T func2() expected(E);<br>T =
func() expected(E) {<br> T v =3D func2();<br> =
yield v*2;<br>}<br><br>Of course syntatic sugar for calling catch_er=
ror might also be useful:<br><br>T func2() expected(E);<br>T func() e=
xpected(E) {<br> do_try {<br> T v =3D func2=
();<br> yield v*2;<br> } catch_er=
ror(E e)<br> {<br> // log e<br> r=
aise e;<br> }<br>}<br><br>What, that reminds me of something....<br><b=
r>With enough syntatic sugar, exceptions and expected are semantically equi=
valent, with the notable difference that the expected error type is statica=
lly checked (but then again you can have except<T, std::any> ). The b=
iggest difference is in the preferred implementation: an explicit CSP trans=
formation with yield/await and non local jumps for exceptions, but either f=
eature could be implemented with either strategy.<br><br>I do like 'expecte=
d' and the fact that the coroutine proposals work as monadic do notation is=
great, but given the history behind C++ we are probably better of with:<br=
><br>* an attribute to ask the compiler to make different trade-off between=
the normal and exceptional case.<br>* the addition of optional static exce=
ption checking which would close the last gap between exceptions and expect=
ed. Static exceptions types are considered a failure in Java, but I believe=
that parametric exception specifications and possibly inference a-la 'thro=
w(auto)' would remove most of the complains of exception specifications. An=
d anyway expected is really equivalent to them.<br><br>-- gpd<br><br><br><b=
r><br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>Greetings,
<br>Nicola
<br>
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_509_1343942930.1433864171295--
------=_Part_508_1040098230.1433864171295--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Tue, 09 Jun 2015 23:56:06 +0200
Raw View
This is a multi-part message in MIME format.
--------------000309060600010905010007
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 09/06/15 17:36, Giovanni Piero Deretta a =C3=A9crit :
> On Sunday, June 7, 2015 at 2:23:50 PM UTC+1, Nicola Gigante wrote:
>
> [...]
>
> Again, high level that means that the following code:
>
> expected<T,E> func2();
> expected<T,E> func() {
> T v =3D await func2();
>
> yield v * 2;
> }
>
> is roughly equivalent to:
>
> expected<T,E> func2();
> expected<T,E> func() {
> expected<T,E> e =3D func2();
>
> return e.then([](T v) {
> return v * 2;
> });
> }
>
>
> Cool. Christopher Kohlhoff and Oliver Kowalke proposed a coroutine=20
> variant which would infer await, so the example would become (IIRC):
>
> expected<T,E> func2();
> expected<T,E> func() {
> T v =3D func2();
>
> return v * 2;
> }
>
> also expected is such a fundamental concept that we might want to add=20
> language support for it, something like:
>
> T func2() expected(E);
> T func() expected(E) {
> T v =3D func2();
> yield v*2;
> }
>
> Of course syntatic sugar for calling catch_error might also be useful:
>
> T func2() expected(E);
> T func() expected(E) {
> do_try {
> T v =3D func2();
> yield v*2;
> } catch_error(E e)
> {
> // log e
> raise e;
> }
> }
>
> What, that reminds me of something....
>
> With enough syntatic sugar, exceptions and expected are semantically=20
> equivalent, with the notable difference that the expected error type=20
> is statically checked (but then again you can have except<T, std::any>=20
> ). The biggest difference is in the preferred implementation: an=20
> explicit CSP transformation with yield/await and non local jumps for=20
> exceptions, but either feature could be implemented with either strategy.
>
> I do like 'expected' and the fact that the coroutine proposals work as=20
> monadic do notation is great, but given the history behind C++ we are=20
> probably better of with:
>
> * an attribute to ask the compiler to make different trade-off between=20
> the normal and exceptional case.
> * the addition of optional static exception checking which would close=20
> the last gap between exceptions and expected. Static exceptions types=20
> are considered a failure in Java, but I believe that parametric=20
> exception specifications and possibly inference a-la 'throw(auto)'=20
> would remove most of the complains of exception specifications. And=20
> anyway expected is really equivalent to them.
>
Thanks Giovanni for describing so clearly the similarities and the=20
differences.
The syntax splitting the return type and the error is awesome, even if=20
what is behind is a return type with either a T or an E.
The removal of await would satisfy more than one.
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------000309060600010905010007
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">Le 09/06/15 17:36, Giovanni Piero
Deretta a =C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:18a21440-69ab-427e-999a-c8f263ff0488@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Sunday, June 7, 2015 at 2:23:50 PM UTC+1, Nicola
Gigante wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
[...]<br>
<br>
Again, high level that means that the following code:
<br>
<br>
expected<T,E> func2();
<br>
expected<T,E> func() {
<br>
=C2=A0 =C2=A0T v =3D await func2();
<br>
<br>
=C2=A0 =C2=A0yield v * 2;
<br>
}
<br>
<br>
is roughly equivalent to:
<br>
<br>
expected<T,E> func2();
<br>
expected<T,E> func() {
<br>
=C2=A0 =C2=A0expected<T,E> e =3D func2();
<br>
<br>
=C2=A0 =C2=A0return e.then([](T v) {
<br>
=C2=A0 =C2=A0 =C2=A0return v * 2;
<br>
=C2=A0 =C2=A0});
<br>
}
<br>
<br>
</blockquote>
<div><br>
Cool. Christopher Kohlhoff and Oliver Kowalke proposed a
coroutine variant which would infer await, so the example
would become (IIRC):<br>
=C2=A0<br>
expected<T,E> func2();
<br>
expected<T,E> func() {
<br>
=C2=A0 =C2=A0T v =3D func2();
<br>
<br>
=C2=A0 return v * 2;
<br>
}
<br>
<br>
also expected is such a fundamental concept that we might want
to add language support for it, something like:<br>
<br>
T func2() expected(E);<br>
T func() expected(E) {<br>
=C2=A0=C2=A0=C2=A0 T v =3D func2();<br>
=C2=A0=C2=A0=C2=A0 yield v*2;<br>
}<br>
<br>
Of course syntatic sugar for calling catch_error=C2=A0 might also
be useful:<br>
<br>
T func2() expected(E);<br>
T func() expected(E) {<br>
=C2=A0=C2=A0 do_try {<br>
=C2=A0 =C2=A0 =C2=A0 T v =3D func2();<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 yield v*2;<br>
=C2=A0=C2=A0 } catch_error(E e)<br>
=C2=A0 {<br>
=C2=A0=C2=A0=C2=A0 // log e<br>
=C2=A0=C2=A0=C2=A0 raise e;<br>
=C2=A0}<br>
}<br>
<br>
What, that reminds me of something....<br>
<br>
With enough syntatic sugar, exceptions and expected are
semantically equivalent, with the notable difference that the
expected error type is statically checked (but then again you
can have except<T, std::any> ). The biggest difference
is in the preferred implementation: an explicit CSP
transformation with yield/await and non local jumps for
exceptions, but either feature could be implemented with
either strategy.<br>
<br>
I do like 'expected' and the fact that the coroutine proposals
work as monadic do notation is great, but given the history
behind C++ we are probably better of with:<br>
<br>
* an attribute to ask the compiler to make different trade-off
between the normal and exceptional case.<br>
* the addition of optional static exception checking which
would close the last gap between exceptions and expected.
Static exceptions types are considered a failure in Java, but
I believe that parametric exception specifications and
possibly inference a-la 'throw(auto)' would remove most of the
complains of exception specifications. And anyway expected is
really equivalent to them.<br>
<br>
</div>
</div>
</blockquote>
Thanks Giovanni for describing so clearly the similarities and the
differences.<br>
The syntax splitting the return type and the error is awesome, even
if what is behind is a return type with either a T or an E.<br>
The removal of await would satisfy more than one.<br>
<br>
Vicente<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------000309060600010905010007--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Tue, 9 Jun 2015 23:19:21 +0100
Raw View
On Tue, Jun 9, 2015 at 10:56 PM, Vicente J. Botet Escriba
<vicente.botet@wanadoo.fr> wrote:
> Le 09/06/15 17:36, Giovanni Piero Deretta a =C3=A9crit :
>
[snip]
>> T func2() expected(E);
>> T func() expected(E) {
>> do_try {
>> T v =3D func2();
>> yield v*2;
>> } catch_error(E e)
>> {
>> // log e
>> raise e;
>> }
>> }
>>
>> What, that reminds me of something....
>>
>> With enough syntatic sugar, exceptions and expected are semantically
>> equivalent, with the notable difference that the expected error type is
>> statically checked (but then again you can have except<T, std::any> ). T=
he
>> biggest difference is in the preferred implementation: an explicit CSP
>> transformation with yield/await and non local jumps for exceptions, but
>> either feature could be implemented with either strategy.
>>[snip]
>
>Thanks Giovanni for describing so clearly the similarities and the
>differences.
thanks!
>The syntax splitting the return type and the error is awesome, even if wha=
t
>is behind is a return type with either a T or an E.
I was trying to be clever and my point was probably lost, but I wasn't
really suggesting that we add that sugar; the syntax I presented is
exactly the same as the usual try {} catch syntax for exceptions but
for the different keywords.
My point was that given enough sugar, expected based code will look
and behave exactly like exception based code with static checking, so
we might as well improve what we already have.
To reiterate,I suggest adding optional static checking exceptions and
encourage compilers to add a more performant implementation for
non-exceptional exceptions.
>The removal of await would satisfy more than one.
on that I agree completely.
-- gpd
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Wed, 10 Jun 2015 17:50:34 +0200
Raw View
> Il giorno 09/giu/2015, alle ore 17:36, Giovanni Piero Deretta <gpderetta@=
gmail.com> ha scritto:
>=20
> Cool. Christopher Kohlhoff and Oliver Kowalke proposed a coroutine varian=
t which would infer await, so the example would become (IIRC):
> =20
> expected<T,E> func2();=20
> expected<T,E> func() {=20
> T v =3D func2();=20
>=20
> return v * 2;=20
> }=20
>=20
> also expected is such a fundamental concept that we might want to add lan=
guage support for it, something like:
>=20
> T func2() expected(E);
> T func() expected(E) {
> T v =3D func2();
> yield v*2;
> }
>=20
> Of course syntatic sugar for calling catch_error might also be useful:
>=20
> T func2() expected(E);
> T func() expected(E) {
> do_try {
> T v =3D func2();
> yield v*2;
> } catch_error(E e)
> {
> // log e
> raise e;
> }
> }
>=20
> What, that reminds me of something=E2=80=A6.
>=20
Yes, that=E2=80=99s familiar indeed :)
> With enough syntatic sugar, exceptions and expected are semantically equi=
valent,
You=E2=80=99re right!
That=E2=80=99s _exactly_ what the abstraction allows us to understand: the =
error handling and propagation _itself_,
not the particular syntax, is a monadic pattern.
But wait, let=E2=80=99s don=E2=80=99t care about monads, ok? Let me call it=
=E2=80=9CBindable=E2=80=9D.
> with the notable difference that the expected error type is statically ch=
ecked (but then again you can have except<T, std::any> ). The biggest diffe=
rence is in the preferred implementation: an explicit CSP transformation wi=
th yield/await and non local jumps for exceptions, but either feature could=
be implemented with either strategy.
>=20
> I do like 'expected' and the fact that the coroutine proposals work as mo=
nadic do notation is great, but given the history behind C++ we are probabl=
y better of with:
>=20
> * an attribute to ask the compiler to make different trade-off between th=
e normal and exceptional case.
> * the addition of optional static exception checking which would close th=
e last gap between exceptions and expected. Static exceptions types are con=
sidered a failure in Java, but I believe that parametric exception specific=
ations and possibly inference a-la 'throw(auto)' would remove most of the c=
omplains of exception specifications. And anyway expected is really equival=
ent to them.
Yes, expected is equivalent to them, except for the syntax! Syntax matters!
Indeed if the type of the thrown exception was part of the type, we=E2=80=
=99d have the static checking, and then we=E2=80=99d have Java exception
specifications. _However_, as I wrote in a previous message, that leads us =
to realize that the problem with java exceptions specifications
is not the specifications themselves, but rather the fact that the try{}cat=
ch{} syntax is not up to the task of conveniently handle the burden
of managing them.
If instead of catching exceptions I could bind a throwing expression in a s=
imilar way as how I can bind an awaitable expression,
then I=E2=80=99d be happy with exceptions:
T throwing() throws(E) { // No C++98 throws(). Let=E2=80=99s pretend the th=
rows() is part of the type
throw E();
}
T func() throws(E) {
T v =3D try throwing();
return v * 2;
}
That=E2=80=99s exactly what we=E2=80=99d gain with expected<T,E> + await: s=
tatic checking and nice syntax.
That=E2=80=99s no more than an automatic catch{ throw; } around the express=
ion,
but compare to Java code:
T func() throws(E) {
try {
T v =3D throwing();
return v * 2;
} catch(E e) {
throw e;
}
}
The above complexity is why java exception specifications are a failure, no=
t the static checking per se.
You=E2=80=99re right that probably this solution is more C++-ish.
But then we=E2=80=99d lose one thing: genericity of syntax.
The coroutines proposal is going to be included in the standard sooner or l=
ater.=20
Then we=E2=80=99d have two different syntaxes when we could have the same:
std::future<T> asyncfunc();
std::future<T> myfunc() {
T v =3D await asyncfunc();
return v * 2;
}
The =E2=80=98await=E2=80=99 keyword is doing exactly the same thing as the =
=E2=80=98try=E2=80=99 keyword in the
example above, but instantiated on two different instances of the same conc=
ept.
That sounds to me _exacly_ as if C++ had different operators for summing in=
teger and floating point values
(as in some numeric computing language out there). No, we have the same sym=
bol for =E2=80=9C+"
because it backs up the same concept. And that=E2=80=99s also why C++ has o=
perator overloading.
(that by going on with the metaphor, is the ability to implement the Awaita=
ble concept for any suitable type
instead of having it hardcoded for, say, future and expected).
The only difference is that the concept of =E2=80=9Csum=E2=80=9D is admitte=
dly more easy to understand than =E2=80=9Cmonad=E2=80=9D (ops, Bindable).
However, C++ exceptions have the advantage that the common case has no runt=
ime overhead,
comparing to expected where the unpacking happens at every bind.=20
However, performance of the throwing path is worse (very worse) that the av=
erage performance of
expected-based code in both paths.
So the right compromise in my opinion is having the two tools coexist and u=
sed each one in its own territory:
exceptions to signal unexpected failures, expected<T> to signal the absence=
of a return value, when this absence
is often the case. And to have the right syntax to handle expected<T> such =
that its static checking feature do
not turn into the java exception specifications failure.
> -- gpd
Greetings,
Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Wed, 10 Jun 2015 10:05:54 -0700 (PDT)
Raw View
------=_Part_731_1523679784.1433955954447
Content-Type: multipart/alternative;
boundary="----=_Part_732_1891122860.1433955954447"
------=_Part_732_1891122860.1433955954447
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, June 10, 2015 at 4:50:41 PM UTC+1, Nicola Gigante wrote:
>
>
> > Il giorno 09/giu/2015, alle ore 17:36, Giovanni Piero Deretta <
> gpde...@gmail.com <javascript:>> ha scritto:=20
> > With enough syntatic sugar, exceptions and expected are semantically=20
> equivalent,=20
>
> [...]
> Yes, expected is equivalent to them, except for the syntax! Syntax=20
> matters!=20
>
that's the point, even with coroutines we would not have enough syntax to=
=20
make expected palatable (unless you want to type await everywhere). If we=
=20
were to add the missing syntax, expected based code would look exactly like=
=20
exception based code. The only advantage of expected is static type=20
checking, which we could (and should) add to exception as well.
=20
> Indeed if the type of the thrown exception was part of the type, we=E2=80=
=99d have=20
> the static checking, and then we=E2=80=99d have Java exception=20
> specifications. _However_, as I wrote in a previous message, that leads u=
s=20
> to realize that the problem with java exceptions specifications=20
> is not the specifications themselves, but rather the fact that the=20
> try{}catch{} syntax is not up to the task of conveniently handle the burd=
en=20
> of managing them.=20
>
As far as I can tell the burden with exception specification in java is=20
that its generic system and compile timpe introspection capabilities are=20
not powerfull enough to abstract over exception types; also you are=20
required to annotate your functions even if you are perfectly happly to let=
=20
it bubble up the stack; its unchecked escape hatch (i.e. RuntimeException)=
=20
is frowned upon but there wouldn't be such a stigma in c++ where dynamic=20
checking would in fact be the norm and static checking would be opt in.
=20
>
> If instead of catching exceptions I could bind a throwing expression in a=
=20
> similar way as how I can bind an awaitable expression,=20
> then I=E2=80=99d be happy with exceptions:=20
>
> T throwing() throws(E) { // No C++98 throws(). Let=E2=80=99s pretend the =
throws()=20
> is part of the type=20
> throw E();=20
> }=20
>
> T func() throws(E) {=20
> T v =3D try throwing();=20
>
> return v * 2;=20
> }=20
>
> That=E2=80=99s exactly what we=E2=80=99d gain with expected<T,E> + await:=
static checking=20
> and nice syntax.=20
>
> That=E2=80=99s no more than an automatic catch{ throw; } around the expre=
ssion,=20
>
Why would you want a try/throw around the expression? That's already=20
implicit in standard c++! The try keyword there is completely superfluous.=
=20
Add static exception specifications and you get the static checking. We=20
already have the nice syntax.
=20
>
> The coroutines proposal is going to be included in the standard sooner or=
=20
> later.=20
> Then we=E2=80=99d have two different syntaxes when we could have the same=
:=20
>
> std::future<T> asyncfunc();=20
>
> std::future<T> myfunc() {=20
> T v =3D await asyncfunc();=20
>
> return v * 2;=20
> }=20
>
> The =E2=80=98await=E2=80=99 keyword is doing exactly the same thing as th=
e =E2=80=98try=E2=80=99 keyword=20
> in the=20
> example above, but instantiated on two different instances of the same=20
> concept.=20
>
That sounds to me _exacly_ as if C++ had different operators for summing=20
> integer and floating point values=20
> (as in some numeric computing language out there). No, we have the same=
=20
> symbol for =E2=80=9C+"=20
> because it backs up the same concept.=20
Exceptions are not recoverable in C++, that's a fundamental difference.=20
Yes, you can simulate exceptions with the continuation monad, that doesn't=
=20
mean you should. For the same reason, we do not use if+goto for eveything=
=20
although it subsumes all looping construct and function calls (which is=20
very relevant as continuations are a *generalization* of goto).=20
=20
As you can trivially translate between the two, 'expected' plus some form=
=20
of 'do notation' is exactly like static exception specifications. I believe=
=20
that compatibility and familiarity with existing C++ error reporting=20
mechanisms strongly suggest we should extend exceptions instead of adding=
=20
yet another error reporting system.=20
[...]
>
> However, C++ exceptions have the advantage that the common case has no=20
> runtime overhead,=20
> comparing to expected where the unpacking happens at every bind.=20
> However, performance of the throwing path is worse (very worse) that the=
=20
> average performance of=20
> expected-based code in both paths.=20
>
That's doesn't have to be the case though, it is just that historically=20
that has been the preferred implementation strategy. An hint (which could=
=20
just be inline + static exception specification) could skew the compiler=20
into preferring a different trade-off in implementing throw. A smart=20
compiler could even maintain ABI compatibilty.
Also a significant part of the complexity is that the exception type is=20
dynamically typed so runtime lookups need to be performed to find the=20
catch target. This wouldn't be the case with static exceptions.
-- gpd=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_732_1891122860.1433955954447
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, June 10, 2015 at 4:50:41 PM UTC+1, Nicola Gi=
gante wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>> Il giorno 09/giu/2015, alle ore 17:36, Giovanni Piero Deretta <=
<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"rdorTnlk=
AzwJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return true=
;" onclick=3D"this.href=3D'javascript:';return true;">gpde...@gmail.com</a>=
> ha scritto:
<br>> With enough syntatic sugar, exceptions and expected are semantical=
ly equivalent,
<br>
<br>[...]<br>Yes, expected is equivalent to them, except for the syntax! Sy=
ntax matters!
<br></blockquote><div><br>that's the point, even with coroutines we would n=
ot have enough syntax to make expected palatable (unless you want to type a=
wait everywhere). If we were to add the missing syntax, expected based code=
would look exactly like exception based code. The only advantage of expect=
ed is static type checking, which we could (and should) add to exception as=
well.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Indeed i=
f the type of the thrown exception was part of the type, we=E2=80=99d have =
the static checking, and then we=E2=80=99d have Java exception
<br>specifications. _However_, as I wrote in a previous message, that leads=
us to realize that the problem with java exceptions specifications
<br>is not the specifications themselves, but rather the fact that the try{=
}catch{} syntax is not up to the task of conveniently handle the burden
<br>of managing them.
<br></blockquote><div><br>As far as I can tell the burden with exception sp=
ecification in java is that its generic system and compile timpe introspect=
ion capabilities are not powerfull enough to=20
abstract over exception types; also you are required to annotate your funct=
ions even if you are perfectly happly to let it bubble up the stack; its un=
checked escape hatch (i.e.=20
RuntimeException) is frowned upon but there wouldn't be such a stigma in
c++ where dynamic checking would in fact be the norm and static=20
checking would be opt in.<br> </div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;">
<br>If instead of catching exceptions I could bind a throwing expression in=
a similar way as how I can bind an awaitable expression,
<br>then I=E2=80=99d be happy with exceptions:
<br>
<br>T throwing() throws(E) { // No C++98 throws(). Let=E2=80=99s pretend th=
e throws() is part of the type
<br> throw E();
<br>}
<br>
<br></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">T func() thro=
ws(E) {
<br> T v =3D try throwing();
<br>
<br> return v * 2;
<br>}
<br>
<br>That=E2=80=99s exactly what we=E2=80=99d gain with expected<T,E> =
+ await: static checking and nice syntax.
<br>
<br>That=E2=80=99s no more than an automatic catch{ throw; } around the exp=
ression,
<br></blockquote><div><br>Why would you want a try/throw around the express=
ion? That's already implicit in standard c++! The try keyword there is comp=
letely superfluous. Add static exception specifications and you get the sta=
tic checking. We already have the nice syntax.<br></div><div> </div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;">
<br></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">The coroutine=
s proposal is going to be included in the standard sooner or later.=20
<br>Then we=E2=80=99d have two different syntaxes when we could have the sa=
me:
<br>
<br>std::future<T> asyncfunc();
<br>
<br>std::future<T> myfunc() {
<br> T v =3D await asyncfunc();
<br>
<br> return v * 2;
<br>}
<br>
<br>The =E2=80=98await=E2=80=99 keyword is doing exactly the same thing as =
the =E2=80=98try=E2=80=99 keyword in the
<br>example above, but instantiated on two different instances of the same =
concept.
<br></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">That sounds t=
o me _exacly_ as if C++ had different operators for summing integer and flo=
ating point values
<br>(as in some numeric computing language out there). No, we have the same=
symbol for =E2=80=9C+"
<br>because it backs up the same concept. </blockquote><div><br>Exceptions =
are not recoverable in C++, that's a fundamental difference. Yes, you can s=
imulate exceptions with the continuation monad, that doesn't mean you shoul=
d. For the same reason, we do not use if+goto for eveything although it sub=
sumes all looping construct and function calls (which is very relevant as c=
ontinuations are a *generalization* of goto). <br> <br>As you can triv=
ially translate between the two, 'expected' plus some=20
form of 'do notation' is exactly like static exception specifications. I be=
lieve that compatibility and familiarity with existing C++ error reporting =
mechanisms strongly suggest we should extend exceptions instead of adding y=
et another error reporting system. <br><br>[...]<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">
<br>However, C++ exceptions have the advantage that the common case has no =
runtime overhead,
<br>comparing to expected where the unpacking happens at every bind.=20
<br>However, performance of the throwing path is worse (very worse) that th=
e average performance of
<br>expected-based code in both paths.
<br></blockquote><div><br>That's doesn't have to be the case though, it is =
just that historically that has been the preferred implementation strategy.=
An hint (which could just be inline + static exception specification) coul=
d skew the compiler into preferring a different trade-off in implementing t=
hrow. A smart compiler could even maintain ABI compatibilty.<br><br>Also a =
significant part of the complexity is that the exception type is dynamicall=
y typed so runtime lookups need to be performed to find the catch tar=
get. This wouldn't be the case with static exceptions.</div><div><br> =
-- gpd
<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_732_1891122860.1433955954447--
------=_Part_731_1523679784.1433955954447--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Wed, 10 Jun 2015 20:16:07 +0200
Raw View
Le 10/06/15 00:19, Giovanni Piero Deretta a =C3=A9crit :
> On Tue, Jun 9, 2015 at 10:56 PM, Vicente J. Botet Escriba
> <vicente.botet@wanadoo.fr> wrote:
>> Le 09/06/15 17:36, Giovanni Piero Deretta a =C3=A9crit :
>>
> [snip]
>>> T func2() expected(E);
>>> T func() expected(E) {
>>> do_try {
>>> T v =3D func2();
>>> yield v*2;
>>> } catch_error(E e)
>>> {
>>> // log e
>>> raise e;
>>> }
>>> }
>>>
>>> What, that reminds me of something....
>>>
>>> With enough syntatic sugar, exceptions and expected are semantically
>>> equivalent, with the notable difference that the expected error type is
>>> statically checked (but then again you can have except<T, std::any> ). =
The
>>> biggest difference is in the preferred implementation: an explicit CSP
>>> transformation with yield/await and non local jumps for exceptions, but
>>> either feature could be implemented with either strategy.
>>> [snip]
>> Thanks Giovanni for describing so clearly the similarities and the
>> differences.
> thanks!
>
>> The syntax splitting the return type and the error is awesome, even if w=
hat
>> is behind is a return type with either a T or an E.
> I was trying to be clever and my point was probably lost, but I wasn't
> really suggesting that we add that sugar;
I understood it
> the syntax I presented is
> exactly the same as the usual try {} catch syntax for exceptions but
> for the different keywords.
>
> My point was that given enough sugar, expected based code will look
> and behave exactly like exception based code with static checking, so
> we might as well improve what we already have.
and I understood it
> To reiterate,I suggest adding optional static checking exceptions and
> encourage compilers to add a more performant implementation for
> non-exceptional exceptions.
and I understood it :)
>
>> The removal of await would satisfy more than one.
> on that I agree completely.
>
> -- gpd
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Wed, 10 Jun 2015 21:43:57 +0200
Raw View
--Apple-Mail=_A123338B-2D52-40D9-8D91-F0AF9ACB5FAB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> Il giorno 10/giu/2015, alle ore 19:05, Giovanni Piero Deretta <gpderetta@=
gmail.com> ha scritto:
>=20
> On Wednesday, June 10, 2015 at 4:50:41 PM UTC+1, Nicola Gigante wrote:
>=20
> > Il giorno 09/giu/2015, alle ore 17:36, Giovanni Piero Deretta <gpde...@=
gmail.com <javascript:>> ha scritto:=20
> > With enough syntatic sugar, exceptions and expected are semantically eq=
uivalent,=20
>=20
> [...]
> Yes, expected is equivalent to them, except for the syntax! Syntax matter=
s!=20
>=20
> that's the point, even with coroutines we would not have enough syntax to=
make expected palatable (unless you want to type await everywhere). If we =
were to add the missing syntax, expected based code would look exactly like=
exception based code. The only advantage of expected is static type checki=
ng, which we could (and should) add to exception as well.
> =20
> Indeed if the type of the thrown exception was part of the type, we=E2=80=
=99d have the static checking, and then we=E2=80=99d have Java exception=20
> specifications. _However_, as I wrote in a previous message, that leads u=
s to realize that the problem with java exceptions specifications=20
> is not the specifications themselves, but rather the fact that the try{}c=
atch{} syntax is not up to the task of conveniently handle the burden=20
> of managing them.=20
>=20
> As far as I can tell the burden with exception specification in java is t=
hat its generic system and compile timpe introspection capabilities are not=
powerfull enough to abstract over exception types; also you are required t=
o annotate your functions even if you are perfectly happly to let it bubble=
up the stack; its unchecked escape hatch (i.e. RuntimeException) is frowne=
d upon but there wouldn't be such a stigma in c++ where dynamic checking wo=
uld in fact be the norm and static checking would be opt in.
> =20
I think this is a matter of taste. To me the burden is the inability to con=
veniently handle the
=E2=80=9CI don=E2=80=99t care, do some work and then just rethrow=E2=80=9D =
case.
>=20
> If instead of catching exceptions I could bind a throwing expression in a=
similar way as how I can bind an awaitable expression,=20
> then I=E2=80=99d be happy with exceptions:=20
>=20
> T throwing() throws(E) { // No C++98 throws(). Let=E2=80=99s pretend the =
throws() is part of the type=20
> throw E();=20
> }=20
>=20
> T func() throws(E) {=20
> T v =3D try throwing();=20
>=20
> return v * 2;=20
> }=20
>=20
> That=E2=80=99s exactly what we=E2=80=99d gain with expected<T,E> + await:=
static checking and nice syntax.=20
>=20
> That=E2=80=99s no more than an automatic catch{ throw; } around the expre=
ssion,=20
>=20
> Why would you want a try/throw around the expression? That's already impl=
icit in standard c++! The try keyword there is completely superfluous. Add =
static exception specifications and you get the static checking. We already=
have the nice syntax.
> =20
I mentally copy-pasted a snippet I wrote some message ago.
Of course the syntax for exceptions is already there.
>=20
> The coroutines proposal is going to be included in the standard sooner or=
later.=20
> Then we=E2=80=99d have two different syntaxes when we could have the same=
:=20
>=20
> std::future<T> asyncfunc();=20
>=20
> std::future<T> myfunc() {=20
> T v =3D await asyncfunc();=20
>=20
> return v * 2;=20
> }=20
>=20
> The =E2=80=98await=E2=80=99 keyword is doing exactly the same thing as th=
e =E2=80=98try=E2=80=99 keyword in the=20
> example above, but instantiated on two different instances of the same co=
ncept.=20
> That sounds to me _exacly_ as if C++ had different operators for summing =
integer and floating point values=20
> (as in some numeric computing language out there). No, we have the same s=
ymbol for =E2=80=9C+"=20
> because it backs up the same concept.
>=20
> Exceptions are not recoverable in C++, that's a fundamental difference. Y=
es, you can simulate exceptions with the continuation monad, that doesn't m=
ean you should. For the same reason, we do not use if+goto for eveything al=
though it subsumes all looping construct and function calls (which is very =
relevant as continuations are a *generalization* of goto).=20
As far as I can tell, it is not the continuation monad, but I could be wron=
g.
Please tell me if turns out that the Either monad is a special case. (but t=
his is OT).
> =20
> As you can trivially translate between the two, 'expected' plus some form=
of 'do notation' is exactly like static exception specifications. I believ=
e that compatibility and familiarity with existing C++ error reporting mech=
anisms strongly suggest we should extend exceptions instead of adding yet a=
nother error reporting system.=20
>=20
> [...]
>=20
> That's doesn't have to be the case though, it is just that historically t=
hat has been the preferred implementation strategy. An hint (which could ju=
st be inline + static exception specification) could skew the compiler into=
preferring a different trade-off in implementing throw. A smart compiler c=
ould even maintain ABI compatibilty.
>=20
> Also a significant part of the complexity is that the exception type is d=
ynamically typed so runtime lookups need to be performed to find the catch=
target. This wouldn't be the case with static exceptions.
>=20
Yes, that they are equivalent is a given (if we had static checking).
We agree on that.
But since expected<T,E> is implementable as pure library code,
and the compiler support for the await syntax is going to be included anywa=
y,
why just do not take advantage of it instead of proposing an extension to t=
he
exceptions mechanism which:
1) require a non-trivial amount of design
2) could require non-trivial implementation changes in current compilers
(for the hint to switch of performance penalty to the non throwing case)
Please understand that I=E2=80=99m not saying that this solution is perfect=
..
There are a lot of unsolved problems.
I=E2=80=99m just saying that what we have now is worse of what we could
have with expected<T,E> + await.=20
On the other hand, it doesn=E2=80=99t mean it has to be _the_ new feature
in error handling. We have std::optional, after all.
Why not all this skepticism for it?
std::expected is just the natural counterpart.=20
> -- gpd=20
Greetings,
Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_A123338B-2D52-40D9-8D91-F0AF9ACB5FAB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">Il giorno 10/giu/201=
5, alle ore 19:05, Giovanni Piero Deretta <<a href=3D"mailto:gpderetta@g=
mail.com" class=3D"">gpderetta@gmail.com</a>> ha scritto:</div><br class=
=3D"Apple-interchange-newline"><div class=3D""><div dir=3D"ltr" class=3D"">=
On Wednesday, June 10, 2015 at 4:50:41 PM UTC+1, Nicola Gigante wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">
<br class=3D"">> Il giorno 09/giu/2015, alle ore 17:36, Giovanni Piero D=
eretta <<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=
=3D"rdorTnlkAzwJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:'=
;return true;" onclick=3D"this.href=3D'javascript:';return true;" class=3D"=
">gpde...@gmail.com</a>> ha scritto:
<br class=3D"">> With enough syntatic sugar, exceptions and expected are=
semantically equivalent,
<br class=3D"">
<br class=3D"">[...]<br class=3D"">Yes, expected is equivalent to them, exc=
ept for the syntax! Syntax matters!
<br class=3D""></blockquote><div class=3D""><br class=3D"">that's the point=
, even with coroutines we would not have enough syntax to make expected pal=
atable (unless you want to type await everywhere). If we were to add the mi=
ssing syntax, expected based code would look exactly like exception based c=
ode. The only advantage of expected is static type checking, which we could=
(and should) add to exception as well.<br class=3D""> </div></div></d=
iv></blockquote><blockquote type=3D"cite" class=3D""><div class=3D""><div d=
ir=3D"ltr" class=3D""><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Indeed i=
f the type of the thrown exception was part of the type, we=E2=80=99d have =
the static checking, and then we=E2=80=99d have Java exception
<br class=3D"">specifications. _However_, as I wrote in a previous message,=
that leads us to realize that the problem with java exceptions specificati=
ons
<br class=3D"">is not the specifications themselves, but rather the fact th=
at the try{}catch{} syntax is not up to the task of conveniently handle the=
burden
<br class=3D"">of managing them.
<br class=3D""></blockquote><div class=3D""><br class=3D"">As far as I can =
tell the burden with exception specification in java is that its generic sy=
stem and compile timpe introspection capabilities are not powerfull enough =
to=20
abstract over exception types; also you are required to annotate your funct=
ions even if you are perfectly happly to let it bubble up the stack; its un=
checked escape hatch (i.e.=20
RuntimeException) is frowned upon but there wouldn't be such a stigma in
c++ where dynamic checking would in fact be the norm and static=20
checking would be opt in.<br class=3D""> </div></div></div></blockquot=
e><div><br class=3D""></div><div>I think this is a matter of taste. To me t=
he burden is the inability to conveniently handle the</div><div>=E2=80=9CI =
don=E2=80=99t care, do some work and then just rethrow=E2=80=9D case.</div>=
<br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div di=
r=3D"ltr" class=3D""><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br class=3D"">If instead of catching exceptions I could bind a throwing ex=
pression in a similar way as how I can bind an awaitable expression,
<br class=3D"">then I=E2=80=99d be happy with exceptions:
<br class=3D"">
<br class=3D"">T throwing() throws(E) { // No C++98 throws(). Let=E2=80=99s=
pretend the throws() is part of the type
<br class=3D""> throw E();
<br class=3D"">}
<br class=3D"">
<br class=3D""></blockquote><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">T =
func() throws(E) {
<br class=3D""> T v =3D try throwing();
<br class=3D"">
<br class=3D""> return v * 2;
<br class=3D"">}
<br class=3D"">
<br class=3D"">That=E2=80=99s exactly what we=E2=80=99d gain with expected&=
lt;T,E> + await: static checking and nice syntax.
<br class=3D"">
<br class=3D"">That=E2=80=99s no more than an automatic catch{ throw; } aro=
und the expression,
<br class=3D""></blockquote><div class=3D""><br class=3D"">Why would you wa=
nt a try/throw around the expression? That's already implicit in standard c=
++! The try keyword there is completely superfluous. Add static exception s=
pecifications and you get the static checking. We already have the nice syn=
tax.<br class=3D""></div><div class=3D""> </div></div></div></blockquo=
te><div><br class=3D""></div><div>I mentally copy-pasted a snippet I wrote =
some message ago.</div><div>Of course the syntax for exceptions is already =
there.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=
=3D""><div dir=3D"ltr" class=3D""><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">
<br class=3D""></blockquote><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Th=
e coroutines proposal is going to be included in the standard sooner or lat=
er.=20
<br class=3D"">Then we=E2=80=99d have two different syntaxes when we could =
have the same:
<br class=3D"">
<br class=3D"">std::future<T> asyncfunc();
<br class=3D"">
<br class=3D"">std::future<T> myfunc() {
<br class=3D""> T v =3D await asyncfunc();
<br class=3D"">
<br class=3D""> return v * 2;
<br class=3D"">}
<br class=3D"">
<br class=3D"">The =E2=80=98await=E2=80=99 keyword is doing exactly the sam=
e thing as the =E2=80=98try=E2=80=99 keyword in the
<br class=3D"">example above, but instantiated on two different instances o=
f the same concept.
<br class=3D""></blockquote><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Th=
at sounds to me _exacly_ as if C++ had different operators for summing inte=
ger and floating point values
<br class=3D"">(as in some numeric computing language out there). No, we ha=
ve the same symbol for =E2=80=9C+"
<br class=3D"">because it backs up the same concept. </blockquote><div clas=
s=3D""><br class=3D"">Exceptions are not recoverable in C++, that's a funda=
mental difference. Yes, you can simulate exceptions with the continuation m=
onad, that doesn't mean you should. For the same reason, we do not use if+g=
oto for eveything although it subsumes all looping construct and function c=
alls (which is very relevant as continuations are a *generalization* of got=
o). <br class=3D""></div></div></div></blockquote><div><br class=3D""></div=
><div>As far as I can tell, it is not the continuation monad, but I could b=
e wrong.</div><div>Please tell me if turns out that the Either monad is a s=
pecial case. (but this is OT).</div><br class=3D""><blockquote type=3D"cite=
" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">&n=
bsp;<br class=3D"">As you can trivially translate between the two, 'expecte=
d' plus some=20
form of 'do notation' is exactly like static exception specifications. I be=
lieve that compatibility and familiarity with existing C++ error reporting =
mechanisms strongly suggest we should extend exceptions instead of adding y=
et another error reporting system. <br class=3D""><br class=3D""></div></di=
v></div></blockquote><blockquote type=3D"cite" class=3D""><div class=3D""><=
div dir=3D"ltr" class=3D""><div class=3D"">[...]<br class=3D""></div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><br class=3D""></blockquote><div cla=
ss=3D"">That's doesn't have to be the case though, it is just that historic=
ally that has been the preferred implementation strategy. An hint (which co=
uld just be inline + static exception specification) could skew the compile=
r into preferring a different trade-off in implementing throw. A smart comp=
iler could even maintain ABI compatibilty.<br class=3D""><br class=3D"">Als=
o a significant part of the complexity is that the exception type is dynami=
cally typed so runtime lookups need to be performed to find the catch=
target. This wouldn't be the case with static exceptions.</div><div class=
=3D""><br class=3D""></div></div></div></blockquote><div><br class=3D""></d=
iv><div><div>Yes, that they are equivalent is a given (if we had static che=
cking).</div><div>We agree on that.</div><div><br class=3D""></div><div>But=
since expected<T,E> is implementable as pure library code,</div><div=
>and the compiler support for the await syntax is going to be included anyw=
ay,</div><div>why just do not take advantage of it instead of proposing an =
extension to the</div><div>exceptions mechanism which:</div><div><br class=
=3D""></div><div>1) require a non-trivial amount of design</div><div>2) cou=
ld require non-trivial implementation changes in current compilers</div><di=
v> (for the hint to switch of performance penalty to the non throwing=
case)</div><div><br class=3D""></div><div>Please understand that I=E2=80=
=99m not saying that this solution is perfect.</div><div>There are a lot of=
unsolved problems.</div><div>I=E2=80=99m just saying that what we have now=
is worse of what we could</div><div>have with expected<T,E> + await.=
</div><div><br class=3D""></div><div>On the other hand, it doesn=E2=
=80=99t mean it has to be _the_ new feature</div><div>in error handling. We=
have std::optional, after all.</div><div>Why not all this skepticism for i=
t?</div><div>std::expected is just the natural counterpart. </div><div=
><br class=3D""></div><div><br class=3D""></div></div><blockquote type=3D"c=
ite" class=3D""><div class=3D""><div dir=3D"ltr" class=3D""><div class=3D""=
> -- gpd
<br class=3D""></div></div></div></blockquote><br class=3D""></div><div>Gre=
etings,</div><div>Nicola</div><br class=3D""></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_A123338B-2D52-40D9-8D91-F0AF9ACB5FAB--
.
Author: Nicola Gigante <nicola.gigante@gmail.com>
Date: Wed, 10 Jun 2015 21:46:33 +0200
Raw View
--Apple-Mail=_E0933C71-2970-4AD9-B55F-BE0B3D3ED10B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
Little correction, to not be misunderstood
> Il giorno 10/giu/2015, alle ore 21:43, Nicola Gigante <nicola.gigante@gma=
il.com> ha scritto:
>=20
> I=E2=80=99m just saying that what we have now is worse of what we could
> have with expected<T,E> + await.=20
>=20
what we could have with expected<T,E> + await used when it=E2=80=99s a good=
idea,
and normal exceptions in the other cases.
> Greetings,
> Nicola
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_E0933C71-2970-4AD9-B55F-BE0B3D3ED10B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><div class=3D""><b=
r class=3D""></div>Little correction, to not be misunderstood<br class=3D""=
><div><blockquote type=3D"cite" class=3D""><div class=3D"">Il giorno 10/giu=
/2015, alle ore 21:43, Nicola Gigante <<a href=3D"mailto:nicola.gigante@=
gmail.com" class=3D"">nicola.gigante@gmail.com</a>> ha scritto:</div><di=
v class=3D""><div style=3D"font-family: Helvetica; font-size: 12px; font-st=
yle: normal; font-variant: normal; font-weight: normal; letter-spacing: nor=
mal; line-height: normal; orphans: auto; text-align: start; text-indent: 0p=
x; text-transform: none; white-space: normal; widows: auto; word-spacing: 0=
px; -webkit-text-stroke-width: 0px;" class=3D""><div class=3D""><br class=
=3D""><div class=3D"">I=E2=80=99m just saying that what we have now is wors=
e of what we could</div><div class=3D"">have with expected<T,E> + awa=
it. </div><div class=3D""><br class=3D""></div></div></div></div></blo=
ckquote>what we could have with expected<T,E> + await used when it=E2=
=80=99s a good idea,</div><div>and normal exceptions in the other cases.<br=
class=3D""><br class=3D""><blockquote type=3D"cite" class=3D""><div class=
=3D""><div style=3D"font-family: Helvetica; font-size: 12px; font-style: no=
rmal; font-variant: normal; font-weight: normal; letter-spacing: normal; li=
ne-height: normal; orphans: auto; text-align: start; text-indent: 0px; text=
-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -we=
bkit-text-stroke-width: 0px;" class=3D"">Greetings,</div><div style=3D"font=
-family: Helvetica; font-size: 12px; font-style: normal; font-variant: norm=
al; font-weight: normal; letter-spacing: normal; line-height: normal; orpha=
ns: auto; text-align: start; text-indent: 0px; text-transform: none; white-=
space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: =
0px;" class=3D"">Nicola</div></div></blockquote></div><div class=3D""><br c=
lass=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_E0933C71-2970-4AD9-B55F-BE0B3D3ED10B--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Wed, 10 Jun 2015 14:23:43 -0700 (PDT)
Raw View
------=_Part_995_1180270655.1433971423295
Content-Type: multipart/alternative;
boundary="----=_Part_996_502451246.1433971423296"
------=_Part_996_502451246.1433971423296
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, June 10, 2015 at 8:44:03 PM UTC+1, Nicola Gigante wrote:
>
>
> Il giorno 10/giu/2015, alle ore 19:05, Giovanni Piero Deretta <
> gpde...@gmail.com <javascript:>> ha scritto:
>
> [...]=20
> Exceptions are not recoverable in C++, that's a fundamental difference.=
=20
> Yes, you can simulate exceptions with the continuation monad, that doesn'=
t=20
> mean you should. For the same reason, we do not use if+goto for eveything=
=20
> although it subsumes all looping construct and function calls (which is=
=20
> very relevant as continuations are a *generalization* of goto).=20
>
>
> As far as I can tell, it is not the continuation monad, but I could be=20
> wrong.
> Please tell me if turns out that the Either monad is a special case. (but=
=20
> this is OT).
>
>
I believe that the either monad is a special case as any monad can be=20
implemented on top of the continuation monad. But you are right of course,=
=20
expected probably is the Either monad. I misspoke as I was thinking of the=
=20
continuation transformation behind the coroutine proposal and I=20
unconsciously made the connection.=20
> =20
> As you can trivially translate between the two, 'expected' plus some form=
=20
> of 'do notation' is exactly like static exception specifications. I belie=
ve=20
> that compatibility and familiarity with existing C++ error reporting=20
> mechanisms strongly suggest we should extend exceptions instead of adding=
=20
> yet another error reporting system.=20
>
> [...]
>
>>
>> That's doesn't have to be the case though, it is just that historically=
=20
> that has been the preferred implementation strategy. An hint (which could=
=20
> just be inline + static exception specification) could skew the compiler=
=20
> into preferring a different trade-off in implementing throw. A smart=20
> compiler could even maintain ABI compatibilty.
>
> Also a significant part of the complexity is that the exception type is=
=20
> dynamically typed so runtime lookups need to be performed to find the=20
> catch target. This wouldn't be the case with static exceptions.
>
>
> Yes, that they are equivalent is a given (if we had static checking).
> We agree on that.
>
> But since expected<T,E> is implementable as pure library code,
> and the compiler support for the await syntax is going to be included=20
> anyway,
> why just do not take advantage of it instead of proposing an extension to=
=20
> the
> exceptions mechanism which:
>
>
if we get the coroutine syntax but committee does not wish to extend the=20
exception model, yes, expected is possibly better than the status quo.
=20
> 1) require a non-trivial amount of design
>
well, so does excepted. Of course there is the non trivial matter that=20
Vincente has already done a good chunk of the work.
=20
> 2) could require non-trivial implementation changes in current compilers
> (for the hint to switch of performance penalty to the non throwing case=
)
>
>
Note that there is a non trivial amount of overhead behind the coroutine=20
syntax as well and that it will take a while for compilers to completely=20
eliminate it. I still do not think the required allocation is eliminable=20
beyond trivial examples.
Please understand that I=E2=80=99m not saying that this solution is perfect=
..
> There are a lot of unsolved problems.
> I=E2=80=99m just saying that what we have now is worse of what we could
> have with expected<T,E> + await.=20
>
> On the other hand, it doesn=E2=80=99t mean it has to be _the_ new feature
> in error handling. We have std::optional, after all.
> Why not all this skepticism for it?
> std::expected is just the natural counterpart.=20
>
>
Well, any error handling model will shape future standard interfaces. Also=
=20
I pity newcomers to C++ that will have to learn all the various error=20
handling models.
Also, we still would not have guidelines for proper error handling. I would=
=20
love that the answer would simply be "use exceptions" in all cases.
-- gpd=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_996_502451246.1433971423296
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, June 10, 2015 at 8:44:03 PM UTC+1, Nicola Gi=
gante wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word=
-wrap:break-word"><br><div><blockquote type=3D"cite"><div>Il giorno 10/giu/=
2015, alle ore 19:05, Giovanni Piero Deretta <<a href=3D"javascript:" ta=
rget=3D"_blank" gdf-obfuscated-mailto=3D"Z3lXDs3_buwJ" rel=3D"nofollow" onm=
ousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D=
'javascript:';return true;">gpde...@gmail.com</a>> ha scritto:</div><br>=
</blockquote></div></div></blockquote><div>[...] <br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><bloc=
kquote type=3D"cite"><div><div dir=3D"ltr"><div>Exceptions are not recovera=
ble in C++, that's a fundamental difference. Yes, you can simulate exceptio=
ns with the continuation monad, that doesn't mean you should. For the same =
reason, we do not use if+goto for eveything although it subsumes all loopin=
g construct and function calls (which is very relevant as continuations are=
a *generalization* of goto). <br></div></div></div></blockquote><div><br><=
/div><div>As far as I can tell, it is not the continuation monad, but I cou=
ld be wrong.</div><div>Please tell me if turns out that the Either monad is=
a special case. (but this is OT).</div><br></div></div></blockquote><div><=
br>I believe that the either monad is a special case as any monad can be im=
plemented on top of the continuation monad. But you are right of course, ex=
pected probably is the Either monad. I misspoke as I was thinking of the co=
ntinuation transformation behind the coroutine proposal and I unconsciously=
made the connection. <br></div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div style=3D"word-wrap:break-word"><div><blockquote type=3D"cite"><div><=
div dir=3D"ltr"><div> <br>As you can trivially translate between the t=
wo, 'expected' plus some=20
form of 'do notation' is exactly like static exception specifications. I be=
lieve that compatibility and familiarity with existing C++ error reporting =
mechanisms strongly suggest we should extend exceptions instead of adding y=
et another error reporting system. <br><br></div></div></div></blockquote><=
blockquote type=3D"cite"><div><div dir=3D"ltr"><div>[...]<br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><br></blockquote><div>That's doesn't have t=
o be the case though, it is just that historically that has been the prefer=
red implementation strategy. An hint (which could just be inline + static e=
xception specification) could skew the compiler into preferring a different=
trade-off in implementing throw. A smart compiler could even maintain ABI =
compatibilty.<br><br>Also a significant part of the complexity is that the =
exception type is dynamically typed so runtime lookups need to be per=
formed to find the catch target. This wouldn't be the case with static exce=
ptions.</div><div><br></div></div></div></blockquote><div><br></div><div><d=
iv>Yes, that they are equivalent is a given (if we had static checking).</d=
iv><div>We agree on that.</div><div><br></div><div>But since expected<T,=
E> is implementable as pure library code,</div><div>and the compiler sup=
port for the await syntax is going to be included anyway,</div><div>why jus=
t do not take advantage of it instead of proposing an extension to the</div=
><div>exceptions mechanism which:</div><div><br></div></div></div></div></b=
lockquote><div><br>if we get the coroutine syntax but committee does not wi=
sh to extend the exception model, yes, expected is possibly better than the=
status quo.<br> </div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv style=3D"word-wrap:break-word"><div><div><div></div><div>1) require a no=
n-trivial amount of design</div></div></div></div></blockquote><div><br>wel=
l, so does excepted. Of course there is the non trivial matter that Vincent=
e has already done a good chunk of the work.<br> </div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div=
><div>2) could require non-trivial implementation changes in current compil=
ers</div><div> (for the hint to switch of performance penalty to the =
non throwing case)</div><div><br></div></div></div></div></blockquote><div>=
<br>Note that there is a non trivial amount of overhead behind the coroutin=
e syntax as well and that it will take a while for compilers to completely =
eliminate it. I still do not think the required allocation is eliminable be=
yond trivial examples.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div style=3D"word-wrap:break-word"><div><div><div></div><div>Please =
understand that I=E2=80=99m not saying that this solution is perfect.</div>=
<div>There are a lot of unsolved problems.</div><div>I=E2=80=99m just sayin=
g that what we have now is worse of what we could</div><div>have with expec=
ted<T,E> + await. </div><div><br></div><div>On the other hand, i=
t doesn=E2=80=99t mean it has to be _the_ new feature</div><div>in error ha=
ndling. We have std::optional, after all.</div><div>Why not all this skepti=
cism for it?</div><div>std::expected is just the natural counterpart. =
</div><div><br></div></div></div></div></blockquote><div><br>Well, any erro=
r handling model will shape future standard interfaces. Also I pity newcome=
rs to C++ that will have to learn all the various error handling models.<br=
>Also, we still would not have guidelines for proper error handling. I woul=
d love that the answer would simply be "use exceptions" in all cases.<br><b=
r> -- gpd
<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_996_502451246.1433971423296--
------=_Part_995_1180270655.1433971423295--
.