Topic: Range-based if versus - await do-catch statement
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Wed, 12 Nov 2014 23:29:46 +0100
Raw View
This is a multi-part message in MIME format.
--------------090909050303000004010100
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 11/11/14 22:34, Matthew Woehlke a =C3=A9crit :
> On 2014-11-11 16:12, Brent Friedman wrote:
>> I've noted in our codebase that we lean heavily on the convenience of
>> range-based for even when it's not perhaps the best way to express an id=
ea.
>>
>> //do something to the first item
>> for (auto& Item : range)
>> {
>> DoSomething(Item);
>> break;
>> }
> auto first_or_null(auto range) -> decltype(&range.begin())
> {
> auto begin =3D range.begin();
> auto end =3D range.end();
> return (begin =3D=3D end ? nullptr : &(*begin));
> }
>
> if (auto item =3D first_or_null(range))
>
> Basically you want that, right? :-)
>
> I'm not sure if that actually works, and it requires an additional
> dereference when you go to use 'item', but OTOH it wouldn't require a
> language change...
>
>
If the result of first_or_null (why not optional<T&>) is configured with=20
*await*, would the following be a good syntax for you?
*do* {
auto& item =3D *await* first_or_null(range)) ;
DoSomething(item);
} *catch* (...) { // if there is no such element
// unsuccessful path...
}
We will need to adapt *await* to jump to the *catch* part instead of=20
returning from the function if there is no value.
This is clearly more complex than your original proposal, but it=20
introduces a mechanism to catch the await errors, which could be=20
applicable to other cases.
I have used *do* instead of *try* to recall the Haskell do-notation, and=20
because the semantic and the efficiency, while close, would be quite=20
different.
Another possibility is to configure directly any range with await
*do* {
auto& item =3D *await* range ;
DoSomething(item);
} *catch* (...) { // if there is no such first element
// unsuccessful path...
}
The next question is, how would perform the generated code ? Would it be=20
as efficient as
if (!std::empty(range)) {
DoSomething(*begin(range));
} else {
// unsuccessful path...
}
Gor what do you think?
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/.
--------------090909050303000004010100
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 11/11/14 22:34, Matthew Woehlke a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote cite=3D"mid:m3tvcu$9ia$1@ger.gmane.org" type=3D"cite">
<pre wrap=3D"">On 2014-11-11 16:12, Brent Friedman wrote:
</pre>
<blockquote type=3D"cite">
<pre wrap=3D"">I've noted in our codebase that we lean heavily on t=
he convenience of
range-based for even when it's not perhaps the best way to express an idea.
//do something to the first item
for (auto& Item : range)
{
DoSomething(Item);
break;
}
</pre>
</blockquote>
<pre wrap=3D"">
auto first_or_null(auto range) -> decltype(&range.begin())
{
auto begin =3D range.begin();
auto end =3D range.end();
return (begin =3D=3D end ? nullptr : &(*begin));
}
if (auto item =3D first_or_null(range))
Basically you want that, right? :-)
I'm not sure if that actually works, and it requires an additional
dereference when you go to use 'item', but OTOH it wouldn't require a
language change...
</pre>
</blockquote>
If the result of first_or_null (why not optional<T&>) is
configured with <b>await</b>, would the following be a good syntax
for you?<br>
<br>
=C2=A0=C2=A0=C2=A0 <b>do</b> { <br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto& item =3D <b>await</b> first_or=
_null(range)) ;<br>
=C2=A0 =C2=A0=C2=A0=C2=A0 DoSomething(item);<br>
=C2=A0=C2=A0=C2=A0 } <b>catch</b> (...) { // if there is no such elemen=
t<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // unsuccessful path... <br>
=C2=A0=C2=A0=C2=A0
}<br>
<br>
We will need to adapt <b>await</b> to jump to the <b>catch</b>
part instead of returning from the function if there is no value.<br>
<br>
This is clearly more complex than your original proposal, but it
introduces a mechanism to catch the await errors, which could be
applicable to other cases. <br>
<br>
I have used <b>do</b> instead of <b>try</b> to recall the Haskell
do-notation, and because the semantic and the efficiency, while
close, would be quite different. <br>
<br>
Another possibility is to configure directly any range with await<br>
<br>
=C2=A0=C2=A0=C2=A0 <b>do</b> { <br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto& item =3D <b>await</b> range ;<=
br>
=C2=A0 =C2=A0=C2=A0=C2=A0 DoSomething(item);<br>
=C2=A0=C2=A0=C2=A0 } <b>catch</b> (...) { // if there is no such first =
element<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // unsuccessful path... <br>
=C2=A0=C2=A0=C2=A0
}<br>
<br>
The next question is, how would perform the generated code ? Would
it be as efficient as<br>
<br>
<div>=C2=A0 if (!std::empty(range)) {<br>
</div>
<div>=C2=A0 =C2=A0 =C2=A0 DoSomething(*begin(range));<br>
=C2=A0 } else {<br>
=C2=A0 =C2=A0=C2=A0 // unsuccessful path... <br>
=C2=A0 }<br>
</div>
<br>
<br>
Gor what do you think?<br>
<br>
Vicente
</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 />
--------------090909050303000004010100--
.
Author: Gor Nishanov <gorn@microsoft.com>
Date: Wed, 12 Nov 2014 23:20:21 +0000
Raw View
--_000_ea89a2cb27274d6bb897412d29b47751BL2PR03MB337namprd03pro_
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I highly recommend small functions and Sean Parent=E2=80=99s suggestion of =
not having more than one for-loop in a function. =E2=98=BA
With smaller functions you can always write:
Void foo() {
for(x: bar()) {
Do Something with X;
Return;
}
Otherwise;
}
Also, if you are OK with using exceptions for control flow =E2=98=BA, then =
you can use optional=E2=80=99s .value() to achieve nearly the same syntax a=
s do-catch.
try {
auto&& item =3D ExpandSomething().value();
DoSomething(item);
} catch (...) { // if there is no such first element
// unsuccessful path...
}
As much as I like N4134 there might be cases where using something else wou=
ld be as good. =E2=98=BA
Gor
P.S.
Await will be useful where you use unconditional error propagation on most =
expands, such as
M<T> f() {
auto x =3D await f1();
auto y =3D await f2(x);
return g(x,y);
}
In those cases where you want to check for an error. You don=E2=80=99t have=
to use await at all for optional or expected.
In case of the future, you may need a wrapper: future<T> -> future<Expected=
<T>>, so that await bar() will strip the temporal expected leaving expected=
<T> enabling you to check for the error.
Thus you can use plain if. No need for try-catch
I.e.
future<T> f() {
auto x =3D await f1();
auto y =3D await WrapErrorWithExpected(f2(x));
if (y.has_error())
return DoSomething();
else
return g(x,y);
}
From: Vicente J. Botet Escriba [mailto:vicente.botet@wanadoo.fr]
Sent: Wednesday, November 12, 2014 2:30 PM
To: std-proposals@isocpp.org; Gor Nishanov
Subject: Re: [std-proposals] Re: Range-based if versus - await do-catch sta=
tement
Le 11/11/14 22:34, Matthew Woehlke a =C3=A9crit :
On 2014-11-11 16:12, Brent Friedman wrote:
I've noted in our codebase that we lean heavily on the convenience of
range-based for even when it's not perhaps the best way to express an idea.
//do something to the first item
for (auto& Item : range)
{
DoSomething(Item);
break;
}
auto first_or_null(auto range) -> decltype(&range.begin())
{
auto begin =3D range.begin();
auto end =3D range.end();
return (begin =3D=3D end ? nullptr : &(*begin));
}
if (auto item =3D first_or_null(range))
Basically you want that, right? :-)
I'm not sure if that actually works, and it requires an additional
dereference when you go to use 'item', but OTOH it wouldn't require a
language change...
If the result of first_or_null (why not optional<T&>) is configured with aw=
ait, would the following be a good syntax for you?
do {
auto& item =3D await first_or_null(range)) ;
DoSomething(item);
} catch (...) { // if there is no such element
// unsuccessful path...
}
We will need to adapt await to jump to the catch part instead of returning =
from the function if there is no value.
This is clearly more complex than your original proposal, but it introduces=
a mechanism to catch the await errors, which could be applicable to other =
cases.
I have used do instead of try to recall the Haskell do-notation, and becaus=
e the semantic and the efficiency, while close, would be quite different.
Another possibility is to configure directly any range with await
do {
auto& item =3D await range ;
DoSomething(item);
} catch (...) { // if there is no such first element
// unsuccessful path...
}
The next question is, how would perform the generated code ? Would it be as=
efficient as
if (!std::empty(range)) {
DoSomething(*begin(range));
} else {
// unsuccessful path...
}
Gor what do you think?
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/.
--_000_ea89a2cb27274d6bb897412d29b47751BL2PR03MB337namprd03pro_
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
//www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8">
<meta name=3D"Generator" content=3D"Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman","serif";
color:black;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0in;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";
color:black;}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:Consolas;
color:black;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Calibri","sans-serif";
color:#1F497D;}
..MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]-->
</head>
<body bgcolor=3D"white" lang=3D"EN-US" link=3D"#0563C1" vlink=3D"#954F72">
<div class=3D"WordSection1">
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">I highly recommend small =
functions and Sean Parent=E2=80=99s suggestion of not having more than one =
for-loop in a function.
</span><span style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D"=
>J</span><span style=3D"font-size:11.0pt;font-family:"Calibri",&q=
uot;sans-serif";color:#1F497D"><o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">With smaller functions yo=
u can always write:<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Void foo() {<o:p></o:p></=
span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> for(x: bar()=
) {
<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> &=
nbsp; Do Something with X;<o:p></o:p></span></=
p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> &=
nbsp; Return;<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> }
<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> Otherwi=
se;<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">}<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Also, if you are OK with =
using exceptions for control flow
</span><span style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D"=
>J</span><span style=3D"font-size:11.0pt;font-family:"Calibri",&q=
uot;sans-serif";color:#1F497D">, then you can use optional=E2=80=99s .=
value() to achieve nearly the same syntax as do-catch.<o:p></o:p></span></p=
>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"> <b>try</b> { <br>
auto&& item =3D ExpandSomething().va=
lue();<br>
DoSomething(item);<br>
} <b>catch</b> (...) { // if there is no such first elem=
ent<br>
// unsuccessful path... <br>
}<br>
<br>
<span style=3D"font-size:11.0pt;font-family:"Calibri","sans-=
serif";color:#1F497D"><o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">As much as I like N4134 t=
here might be cases where using something else would be as good.
</span><span style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D"=
>J</span><span style=3D"font-size:11.0pt;font-family:"Calibri",&q=
uot;sans-serif";color:#1F497D"><o:p></o:p></span></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b>Gor<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b>P.S.<o:p></o:p></b></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Await will be useful wher=
e you use unconditional error propagation on most expands, such as<o:p></o:=
p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">M<T> f() {<o:p></o:=
p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> auto x=
=3D await f1();<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> auto y=
=3D await f2(x);<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> return=
g(x,y);<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">}<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">In those cases where you =
want to check for an error. You don=E2=80=99t have to use await at all for =
optional or expected.<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">In case of the future, yo=
u may need a wrapper: future<T> -> future<Expected<T>>=
, so that await bar() will strip the temporal expected leaving expected<=
T> enabling
you to check for the error.<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Thus you can use plain if=
.. No need for try-catch<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">I.e.<o:p></o:p></span></p=
>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">future<T> f() {<o:p=
></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> auto x=
=3D await f1();<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> auto y=
=3D await WrapErrorWithExpected(f2(x));<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> if (y.=
has_error())
<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> &=
nbsp; return DoSomething();<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> else<o=
:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> =
return g(x,y);<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">}<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<div>
<div style=3D"border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in =
0in 0in">
<p class=3D"MsoNormal"><b><span style=3D"font-size:11.0pt;font-family:"=
;Calibri","sans-serif";color:windowtext">From:</span></b><sp=
an style=3D"font-size:11.0pt;font-family:"Calibri","sans-ser=
if";color:windowtext"> Vicente J. Botet Escriba [mailto:vicente.botet@=
wanadoo.fr]
<br>
<b>Sent:</b> Wednesday, November 12, 2014 2:30 PM<br>
<b>To:</b> std-proposals@isocpp.org; Gor Nishanov<br>
<b>Subject:</b> Re: [std-proposals] Re: Range-based if versus - await do-ca=
tch statement<o:p></o:p></span></p>
</div>
</div>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<div>
<p class=3D"MsoNormal">Le 11/11/14 22:34, Matthew Woehlke a =C3=A9crit =
;:<o:p></o:p></p>
</div>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<pre>On 2014-11-11 16:12, Brent Friedman wrote:<o:p></o:p></pre>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<pre>I've noted in our codebase that we lean heavily on the convenience of<=
o:p></o:p></pre>
<pre>range-based for even when it's not perhaps the best way to express an =
idea.<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>//do something to the first item<o:p></o:p></pre>
<pre>for (auto& Item : range)<o:p></o:p></pre>
<pre>{<o:p></o:p></pre>
<pre> DoSomething(Item);<o:p></o:p></pre>
<pre> break;<o:p></o:p></pre>
<pre>}<o:p></o:p></pre>
</blockquote>
<pre><o:p> </o:p></pre>
<pre> auto first_or_null(auto range) -> decltype(&=
range.begin())<o:p></o:p></pre>
<pre> {<o:p></o:p></pre>
<pre> auto begin =3D range.begin(=
);<o:p></o:p></pre>
<pre> auto end =3D range.end();<o=
:p></o:p></pre>
<pre> return (begin =3D=3D end ? =
nullptr : &(*begin));<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre> if (auto item =3D first_or_null(range))<o:p></o:p><=
/pre>
<pre><o:p> </o:p></pre>
<pre>Basically you want that, right? :-)<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>I'm not sure if that actually works, and it requires an additional<o:p=
></o:p></pre>
<pre>dereference when you go to use 'item', but OTOH it wouldn't require a<=
o:p></o:p></pre>
<pre>language change...<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre><o:p> </o:p></pre>
</blockquote>
<p class=3D"MsoNormal" style=3D"margin-bottom:12.0pt">If the result of firs=
t_or_null (why not optional<T&>) is configured with
<b>await</b>, would the following be a good syntax for you?<br>
<br>
<b>do</b> { <br>
auto& item =3D <b>await</b> first_or_nul=
l(range)) ;<br>
DoSomething(item);<br>
} <b>catch</b> (...) { // if there is no such element<br=
>
// unsuccessful path... <br>
}<br>
<br>
We will need to adapt <b>await</b> to jump to the <b>catch</b> part instead=
of returning from the function if there is no value.<br>
<br>
This is clearly more complex than your original proposal, but it introduces=
a mechanism to catch the await errors, which could be applicable to other =
cases.
<br>
<br>
I have used <b>do</b> instead of <b>try</b> to recall the Haskell do-notati=
on, and because the semantic and the efficiency, while close, would be quit=
e different.
<br>
<br>
Another possibility is to configure directly any range with await<br>
<br>
<b>do</b> { <br>
auto& item =3D <b>await</b> range ;<br>
DoSomething(item);<br>
} <b>catch</b> (...) { // if there is no such first elem=
ent<br>
// unsuccessful path... <br>
}<br>
<br>
The next question is, how would perform the generated code ? Would it be as=
efficient as<o:p></o:p></p>
<div>
<p class=3D"MsoNormal"> if (!std::empty(range)) {<o:p></o:p></p>
</div>
<div>
<p class=3D"MsoNormal"> DoSomething(*begin(range));<br>
} else {<br>
// unsuccessful path... <br>
}<o:p></o:p></p>
</div>
<p class=3D"MsoNormal"><br>
<br>
Gor what do you think?<br>
<br>
Vicente <o:p></o:p></p>
</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 />
--_000_ea89a2cb27274d6bb897412d29b47751BL2PR03MB337namprd03pro_--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Thu, 13 Nov 2014 01:10:07 +0100
Raw View
This is a multi-part message in MIME format.
--------------080204000206010400090406
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 13/11/14 00:20, Gor Nishanov a =C3=A9crit :
>
> I highly recommend small functions and Sean Parent=E2=80=99s suggestion o=
f not=20
> having more than one for-loop in a function. J
>
> With smaller functions you can always write:
>
> Void foo() {
>
> for(x: bar()) {
>
> Do Something with X;
>
> Return;
>
> }
>
> Otherwise;
>
> }
>
> Also, if you are OK with using exceptions for control flow J, then you=20
> can use optional=E2=80=99s .value() to achieve nearly the same syntax as =
do-catch.
>
> *try* {
> auto&& item =3D ExpandSomething().value();
> DoSomething(item);
> } *catch* (...) { // if there is no such first element
> // unsuccessful path...
> }
>
This make use of exceptions, that if I'm not wrong, is more expensive=20
that just a jump.
>
> As much as I like N4134 there might be cases where using something=20
> else would be as good. J
>
> **
>
> *Gor*
>
> **
>
> *P.S.*
>
> Await will be useful where you use unconditional error propagation on=20
> most expands, such as
>
> M<T> f() {
>
> auto x =3D await f1();
>
> auto y =3D await f2(x);
>
> return g(x,y);
>
> }
>
> In those cases where you want to check for an error. You don=E2=80=99t ha=
ve to=20
> use await at all for optional or expected.
>
> In case of the future, you may need a wrapper: future<T> ->=20
> future<Expected<T>>, so that await bar() will strip the temporal=20
> expected leaving expected<T> enabling you to check for the error.
>
> Thus you can use plain if. No need for try-catch
>
> I.e.
>
> future<T> f() {
>
> auto x =3D await f1();
>
> auto y =3D await WrapErrorWithExpected(f2(x));
>
> if (y.has_error())
>
> return DoSomething();
>
> else
>
> return g(x,y);
>
> }
>
This is the same as returning optional<T> directly, which impose to make=20
use of operator*(). I don't see the interest of the nesting.
Could you come back to the OP example?
My do-catch suggestion has the advantage to don't need to dereference=20
the result and probably been more efficient than using exceptions.
It is very similar to the Haskell do-notation for MonadError
do { action1; action2; action3 } `catchError` handler
Vicente
> *From:*Vicente J. Botet Escriba [mailto:vicente.botet@wanadoo.fr]
> *Sent:* Wednesday, November 12, 2014 2:30 PM
> *To:* std-proposals@isocpp.org; Gor Nishanov
> *Subject:* Re: [std-proposals] Re: Range-based if versus - await=20
> do-catch statement
>
> Le 11/11/14 22:34, Matthew Woehlke a =C3=A9crit :
>
> On 2014-11-11 16:12, Brent Friedman wrote:
>
> I've noted in our codebase that we lean heavily on the convenienc=
e of
>
> range-based for even when it's not perhaps the best way to expres=
s an idea.
>
> =20
>
> //do something to the first item
>
> for (auto& Item : range)
>
> {
>
> DoSomething(Item);
>
> break;
>
> }
>
> =20
>
> auto first_or_null(auto range) -> decltype(&range.begin())
>
> {
>
> auto begin =3D range.begin();
>
> auto end =3D range.end();
>
> return (begin =3D=3D end ? nullptr : &(*begin));
>
> }
>
> =20
>
> if (auto item =3D first_or_null(range))
>
> =20
>
> Basically you want that, right? :-)
>
> =20
>
> I'm not sure if that actually works, and it requires an additional
>
> dereference when you go to use 'item', but OTOH it wouldn't require a
>
> language change...
>
> =20
>
> =20
>
> If the result of first_or_null (why not optional<T&>) is configured=20
> with *await*, would the following be a good syntax for you?
>
> *do* {
> auto& item =3D *await* first_or_null(range)) ;
> DoSomething(item);
> } *catch* (...) { // if there is no such element
> // unsuccessful path...
> }
>
> We will need to adapt *await* to jump to the *catch* part instead of=20
> returning from the function if there is no value.
>
> This is clearly more complex than your original proposal, but it=20
> introduces a mechanism to catch the await errors, which could be=20
> applicable to other cases.
>
> I have used *do* instead of *try* to recall the Haskell do-notation,=20
> and because the semantic and the efficiency, while close, would be=20
> quite different.
>
> Another possibility is to configure directly any range with await
>
> *do* {
> auto& item =3D *await* range ;
> DoSomething(item);
> } *catch* (...) { // if there is no such first element
> // unsuccessful path...
> }
>
> The next question is, how would perform the generated code ? Would it=20
> be as efficient as
>
> if (!std::empty(range)) {
>
> DoSomething(*begin(range));
> } else {
> // unsuccessful path...
> }
>
>
>
> Gor what do you think?
>
> 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/.
--------------080204000206010400090406
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 13/11/14 00:20, Gor Nishanov a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:ea89a2cb27274d6bb897412d29b47751@BL2PR03MB337.namprd03.prod.out=
look.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3DUTF=
-8">
<meta name=3D"Generator" content=3D"Microsoft Word 15 (filtered
medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman","serif";
color:black;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0in;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";
color:black;}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:Consolas;
color:black;}
span.EmailStyle19
{mso-style-type:personal-reply;
font-family:"Calibri","sans-serif";
color:#1F497D;}
..MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]-->
<div class=3D"WordSection1">
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">I
highly recommend small functions and Sean Parent=E2=80=99s
suggestion of not having more than one for-loop in a
function.
</span><span
style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D">=
J</span><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">With
smaller functions you can always write:<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">Void
foo() {<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0
for(x: bar()) {
<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0Do
Something with X;<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0
Return;<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0
}
<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0Otherwise;<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">}<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">Also,
if you are OK with using exceptions for control flow
</span><span
style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D">=
J</span><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">,
then you can use optional=E2=80=99s .value() to achieve nearly =
the
same syntax as do-catch.<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal">=C2=A0=C2=A0=C2=A0 <b>try</b> { <br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto&& item =3D ExpandSome=
thing().value();<br>
=C2=A0 =C2=A0=C2=A0=C2=A0 DoSomething(item);<br>
=C2=A0=C2=A0=C2=A0 } <b>catch</b> (...) { // if there is no such =
first
element<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // unsuccessful path... <br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
<span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p></o:p></span></p>
</div>
</blockquote>
This make use of exceptions, that if I'm not wrong, is more
expensive that just a jump.<br>
<blockquote
cite=3D"mid:ea89a2cb27274d6bb897412d29b47751@BL2PR03MB337.namprd03.prod.out=
look.com"
type=3D"cite">
<div class=3D"WordSection1">
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">As
much as I like N4134 there might be cases where using
something else would be as good.
</span><span
style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D">=
J</span><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p></o:p></span></p>
<p class=3D"MsoNormal"><b><o:p>=C2=A0</o:p></b></p>
<p class=3D"MsoNormal"><b>Gor<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p>=C2=A0</o:p></b></p>
<p class=3D"MsoNormal"><b>P.S.<o:p></o:p></b></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">Await
will be useful where you use unconditional error propagation
on most expands, such as<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">M<T>
f() {<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0
auto x =3D await f1();<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0
auto y =3D await f2(x);<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0
return g(x,y);<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">}<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">In
those cases where you want to check for an error. You don=E2=80=
=99t
have to use await at all for optional or expected.<o:p></o:p></=
span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">In
case of the future, you may need a wrapper: future<T>
-> future<Expected<T>>, so that await bar()
will strip the temporal expected leaving expected<T>
enabling you to check for the error.<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">Thus
you can use plain if. No need for try-catch<o:p></o:p></span></=
p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">I.e.<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">future<T>
f() {<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0
auto x =3D await f1();<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0
auto y =3D await WrapErrorWithExpected(f2(x));<o:p></o:p></span=
></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0
if (y.has_error())
<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return
DoSomething();<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0
else<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">=C2=A0=C2=A0=C2=A0
=C2=A0=C2=A0=C2=A0=C2=A0return g(x,y);<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D">}<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:#1F497D"><o:p>=C2=A0</o:p></span></p>
</div>
</blockquote>
This is the same as returning optional<T> directly, which
impose to make use of operator*(). I don't see the interest of the
nesting.<br>
Could you come back to the OP example?<br>
My do-catch suggestion has the advantage to don't need to
dereference the result and probably been more efficient than using
exceptions.<br>
<br>
It is very similar to the Haskell do-notation for MonadError<br>
<br>
<meta http-equiv=3D"content-type" content=3D"text/html; charset=3DUTF-8=
">
<pre>do { action1; action2; action3 } `catchError` handler
</pre>
<br>
<br>
Vicente <br>
<br>
<blockquote
cite=3D"mid:ea89a2cb27274d6bb897412d29b47751@BL2PR03MB337.namprd03.prod.out=
look.com"
type=3D"cite">
<div class=3D"WordSection1">
<div>
<div style=3D"border:none;border-top:solid #E1E1E1
1.0pt;padding:3.0pt 0in 0in 0in">
<p class=3D"MsoNormal"><b><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:windowtext">From:</span></b><span
style=3D"font-size:11.0pt;font-family:"Calibri","sans-serif&=
quot;;color:windowtext">
Vicente J. Botet Escriba
[<a class=3D"moz-txt-link-freetext" href=3D"mailto:vicente.=
botet@wanadoo.fr">mailto:vicente.botet@wanadoo.fr</a>]
<br>
<b>Sent:</b> Wednesday, November 12, 2014 2:30 PM<br>
<b>To:</b> <a class=3D"moz-txt-link-abbreviated" href=3D"ma=
ilto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>; Gor Nishanov<b=
r>
<b>Subject:</b> Re: [std-proposals] Re: Range-based if
versus - await do-catch statement<o:p></o:p></span></p>
</div>
</div>
<p class=3D"MsoNormal"><o:p>=C2=A0</o:p></p>
<div>
<p class=3D"MsoNormal">Le 11/11/14 22:34, Matthew Woehlke a
=C3=A9crit=C2=A0:<o:p></o:p></p>
</div>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<pre>On 2014-11-11 16:12, Brent Friedman wrote:<o:p></o:p></pre>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<pre>I've noted in our codebase that we lean heavily on the con=
venience of<o:p></o:p></pre>
<pre>range-based for even when it's not perhaps the best way to=
express an idea.<o:p></o:p></pre>
<pre><o:p>=C2=A0</o:p></pre>
<pre>//do something to the first item<o:p></o:p></pre>
<pre>for (auto& Item : range)<o:p></o:p></pre>
<pre>{<o:p></o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0 DoSomething(Item);<o:p></o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0 break;<o:p></o:p></pre>
<pre>}<o:p></o:p></pre>
</blockquote>
<pre><o:p>=C2=A0</o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0 auto first_or_null(auto range) -> decl=
type(&range.begin())<o:p></o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0 {<o:p></o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto begin =3D ra=
nge.begin();<o:p></o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto end =3D rang=
e.end();<o:p></o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return (begin =3D=
=3D end ? nullptr : &(*begin));<o:p></o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0 }<o:p></o:p></pre>
<pre><o:p>=C2=A0</o:p></pre>
<pre>=C2=A0=C2=A0=C2=A0 if (auto item =3D first_or_null(range))<o=
:p></o:p></pre>
<pre><o:p>=C2=A0</o:p></pre>
<pre>Basically you want that, right? :-)<o:p></o:p></pre>
<pre><o:p>=C2=A0</o:p></pre>
<pre>I'm not sure if that actually works, and it requires an addi=
tional<o:p></o:p></pre>
<pre>dereference when you go to use 'item', but OTOH it wouldn't =
require a<o:p></o:p></pre>
<pre>language change...<o:p></o:p></pre>
<pre><o:p>=C2=A0</o:p></pre>
<pre><o:p>=C2=A0</o:p></pre>
</blockquote>
<p class=3D"MsoNormal" style=3D"margin-bottom:12.0pt">If the result
of first_or_null (why not optional<T&>) is
configured with
<b>await</b>, would the following be a good syntax for you?<br>
<br>
=C2=A0=C2=A0=C2=A0 <b>do</b> { <br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto& item =3D <b>await</b> fi=
rst_or_null(range)) ;<br>
=C2=A0 =C2=A0=C2=A0=C2=A0 DoSomething(item);<br>
=C2=A0=C2=A0=C2=A0 } <b>catch</b> (...) { // if there is no such =
element<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // unsuccessful path... <br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
We will need to adapt <b>await</b> to jump to the <b>catch</b>
part instead of returning from the function if there is no
value.<br>
<br>
This is clearly more complex than your original proposal, but
it introduces a mechanism to catch the await errors, which
could be applicable to other cases.
<br>
<br>
I have used <b>do</b> instead of <b>try</b> to recall the
Haskell do-notation, and because the semantic and the
efficiency, while close, would be quite different.
<br>
<br>
Another possibility is to configure directly any range with
await<br>
<br>
=C2=A0=C2=A0=C2=A0 <b>do</b> { <br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto& item =3D <b>await</b> ra=
nge ;<br>
=C2=A0 =C2=A0=C2=A0=C2=A0 DoSomething(item);<br>
=C2=A0=C2=A0=C2=A0 } <b>catch</b> (...) { // if there is no such =
first
element<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // unsuccessful path... <br>
=C2=A0=C2=A0=C2=A0 }<br>
<br>
The next question is, how would perform the generated code ?
Would it be as efficient as<o:p></o:p></p>
<div>
<p class=3D"MsoNormal">=C2=A0 if (!std::empty(range)) {<o:p></o:p=
></p>
</div>
<div>
<p class=3D"MsoNormal">=C2=A0 =C2=A0 =C2=A0 DoSomething(*begin(ra=
nge));<br>
=C2=A0 } else {<br>
=C2=A0 =C2=A0=C2=A0 // unsuccessful path... <br>
=C2=A0 }<o:p></o:p></p>
</div>
<p class=3D"MsoNormal"><br>
<br>
Gor what do you think?<br>
<br>
Vicente <o:p></o:p></p>
</div>
</blockquote>
<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 />
--------------080204000206010400090406--
.
Author: Gor Nishanov <gorn@microsoft.com>
Date: Thu, 13 Nov 2014 01:59:01 +0000
Raw View
--_000_6e1462b914214c95a4ff7102f53a9755BL2PR03MB337namprd03pro_
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I think it is a cool idea.
Though for me to become enthusiastic about it, I need to see a real example=
where using do-catch is significantly better than using smaller functions =
(or even named lambdas).
Essentially, I think that if the same goal can be achieved by structuring y=
our code differently, it is goodness.
Also, I would like to keep the initial proposal small to ensure ease of pas=
sing. Once it is in, we can pile on to add more things on top =E2=98=BA.
In my example in PS, I was using futures, thus await was needed to strip te=
mporal aspect. I was using Wrap to prevent expansion of error. As I mention=
ed before Wrap was doing: future<T> -> future<expected<T>> transformation. =
Await only strips one level, allowing expected to be checked for errors pri=
or to dereference.
Gor
From: Vicente J. Botet Escriba [mailto:vicente.botet@wanadoo.fr]
Sent: Wednesday, November 12, 2014 4:10 PM
To: Gor Nishanov; std-proposals@isocpp.org
Subject: Re: [std-proposals] Re: Range-based if versus - await do-catch sta=
tement
Le 13/11/14 00:20, Gor Nishanov a =C3=A9crit :
I highly recommend small functions and Sean Parent=E2=80=99s suggestion of =
not having more than one for-loop in a function. =E2=98=BA
With smaller functions you can always write:
Void foo() {
for(x: bar()) {
Do Something with X;
Return;
}
Otherwise;
}
Also, if you are OK with using exceptions for control flow =E2=98=BA, then =
you can use optional=E2=80=99s .value() to achieve nearly the same syntax a=
s do-catch.
try {
auto&& item =3D ExpandSomething().value();
DoSomething(item);
} catch (...) { // if there is no such first element
// unsuccessful path...
}
This make use of exceptions, that if I'm not wrong, is more expensive that =
just a jump.
As much as I like N4134 there might be cases where using something else wou=
ld be as good. =E2=98=BA
Gor
P.S.
Await will be useful where you use unconditional error propagation on most =
expands, such as
M<T> f() {
auto x =3D await f1();
auto y =3D await f2(x);
return g(x,y);
}
In those cases where you want to check for an error. You don=E2=80=99t have=
to use await at all for optional or expected.
In case of the future, you may need a wrapper: future<T> -> future<Expected=
<T>>, so that await bar() will strip the temporal expected leaving expected=
<T> enabling you to check for the error.
Thus you can use plain if. No need for try-catch
I.e.
future<T> f() {
auto x =3D await f1();
auto y =3D await WrapErrorWithExpected(f2(x));
if (y.has_error())
return DoSomething();
else
return g(x,y);
}
This is the same as returning optional<T> directly, which impose to make us=
e of operator*(). I don't see the interest of the nesting.
Could you come back to the OP example?
My do-catch suggestion has the advantage to don't need to dereference the r=
esult and probably been more efficient than using exceptions.
It is very similar to the Haskell do-notation for MonadError
do { action1; action2; action3 } `catchError` handler
Vicente
From: Vicente J. Botet Escriba [mailto:vicente.botet@wanadoo.fr]
Sent: Wednesday, November 12, 2014 2:30 PM
To: std-proposals@isocpp.org<mailto:std-proposals@isocpp.org>; Gor Nishanov
Subject: Re: [std-proposals] Re: Range-based if versus - await do-catch sta=
tement
Le 11/11/14 22:34, Matthew Woehlke a =C3=A9crit :
On 2014-11-11 16:12, Brent Friedman wrote:
I've noted in our codebase that we lean heavily on the convenience of
range-based for even when it's not perhaps the best way to express an idea.
//do something to the first item
for (auto& Item : range)
{
DoSomething(Item);
break;
}
auto first_or_null(auto range) -> decltype(&range.begin())
{
auto begin =3D range.begin();
auto end =3D range.end();
return (begin =3D=3D end ? nullptr : &(*begin));
}
if (auto item =3D first_or_null(range))
Basically you want that, right? :-)
I'm not sure if that actually works, and it requires an additional
dereference when you go to use 'item', but OTOH it wouldn't require a
language change...
If the result of first_or_null (why not optional<T&>) is configured with aw=
ait, would the following be a good syntax for you?
do {
auto& item =3D await first_or_null(range)) ;
DoSomething(item);
} catch (...) { // if there is no such element
// unsuccessful path...
}
We will need to adapt await to jump to the catch part instead of returning =
from the function if there is no value.
This is clearly more complex than your original proposal, but it introduces=
a mechanism to catch the await errors, which could be applicable to other =
cases.
I have used do instead of try to recall the Haskell do-notation, and becaus=
e the semantic and the efficiency, while close, would be quite different.
Another possibility is to configure directly any range with await
do {
auto& item =3D await range ;
DoSomething(item);
} catch (...) { // if there is no such first element
// unsuccessful path...
}
The next question is, how would perform the generated code ? Would it be as=
efficient as
if (!std::empty(range)) {
DoSomething(*begin(range));
} else {
// unsuccessful path...
}
Gor what do you think?
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/.
--_000_6e1462b914214c95a4ff7102f53a9755BL2PR03MB337namprd03pro_
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
//www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8">
<meta name=3D"Generator" content=3D"Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman","serif";
color:black;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0in;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";
color:black;}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:Consolas;
color:black;}
span.EmailStyle19
{mso-style-type:personal;
font-family:"Calibri","sans-serif";
color:#1F497D;}
span.EmailStyle20
{mso-style-type:personal;
font-family:"Calibri","sans-serif";
color:#1F497D;}
span.EmailStyle21
{mso-style-type:personal-compose;
font-family:"Calibri","sans-serif";
color:windowtext;}
..MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]-->
</head>
<body bgcolor=3D"white" lang=3D"EN-US" link=3D"#0563C1" vlink=3D"#954F72">
<div class=3D"WordSection1">
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">I think it is a cool idea=
..<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Though for me to become e=
nthusiastic about it, I need to see a real example where using do-catch is =
significantly better than using smaller functions (or even
named lambdas).<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Essentially, I think that=
if the same goal can be achieved by structuring your code differently, it =
is goodness.<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Also, I would like to kee=
p the initial proposal small to ensure ease of passing. Once it is in, we c=
an pile on to add more things on top
</span><span style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D"=
>J</span><span style=3D"font-size:11.0pt;font-family:"Calibri",&q=
uot;sans-serif";color:#1F497D">.<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">In my example in PS, I wa=
s using futures, thus await was needed to strip temporal aspect. I was usin=
g Wrap to prevent expansion of error. As I mentioned before
Wrap was doing: future<T> -> future<expected<T>> tran=
sformation. Await only strips one level, allowing expected to be checked fo=
r errors prior to dereference.<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Gor<o:p></o:p></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"><o:p> </o:p></span><=
/p>
<div>
<div style=3D"border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in =
0in 0in">
<p class=3D"MsoNormal"><b><span style=3D"font-size:11.0pt;font-family:"=
;Calibri","sans-serif";color:windowtext">From:</span></b><sp=
an style=3D"font-size:11.0pt;font-family:"Calibri","sans-ser=
if";color:windowtext"> Vicente J. Botet Escriba [mailto:vicente.botet@=
wanadoo.fr]
<br>
<b>Sent:</b> Wednesday, November 12, 2014 4:10 PM<br>
<b>To:</b> Gor Nishanov; std-proposals@isocpp.org<br>
<b>Subject:</b> Re: [std-proposals] Re: Range-based if versus - await do-ca=
tch statement<o:p></o:p></span></p>
</div>
</div>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<div>
<p class=3D"MsoNormal">Le 13/11/14 00:20, Gor Nishanov a =C3=A9crit :<=
o:p></o:p></p>
</div>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">I highly recommend small =
functions and Sean Parent=E2=80=99s suggestion of not having more than one =
for-loop in a function.
</span><span style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D"=
>J</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">With smaller functions yo=
u can always write:</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Void foo() {</span><o:p><=
/o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> for(x: bar()=
) {
</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> &=
nbsp; Do Something with X;</span><o:p></o:p></=
p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> &=
nbsp; Return;</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> }
</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> Otherwi=
se;</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">}</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Also, if you are OK with =
using exceptions for control flow
</span><span style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D"=
>J</span><span style=3D"font-size:11.0pt;font-family:"Calibri",&q=
uot;sans-serif";color:#1F497D">, then you can use optional=E2=80=99s .=
value() to achieve nearly the same syntax as do-catch.</span><o:p></o:p></p=
>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"> <b>try</b> { <br>
auto&& item =3D ExpandSomething().va=
lue();<br>
DoSomething(item);<br>
} <b>catch</b> (...) { // if there is no such first elem=
ent<br>
// unsuccessful path... <br>
}<br>
<br>
<br>
<o:p></o:p></p>
</blockquote>
<p class=3D"MsoNormal">This make use of exceptions, that if I'm not wrong, =
is more expensive that just a jump.<br>
<br>
<o:p></o:p></p>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">As much as I like N4134 t=
here might be cases where using something else would be as good.
</span><span style=3D"font-size:11.0pt;font-family:Wingdings;color:#1F497D"=
>J</span><o:p></o:p></p>
<p class=3D"MsoNormal"><b> </b><o:p></o:p></p>
<p class=3D"MsoNormal"><b>Gor</b><o:p></o:p></p>
<p class=3D"MsoNormal"><b> </b><o:p></o:p></p>
<p class=3D"MsoNormal"><b>P.S.</b><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Await will be useful wher=
e you use unconditional error propagation on most expands, such as</span><o=
:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">M<T> f() {</span><o=
:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> auto x=
=3D await f1();</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> auto y=
=3D await f2(x);</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> return=
g(x,y);</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">}</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">In those cases where you =
want to check for an error. You don=E2=80=99t have to use await at all for =
optional or expected.</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">In case of the future, yo=
u may need a wrapper: future<T> -> future<Expected<T>>=
, so that await bar() will strip the temporal expected leaving expected<=
T> enabling
you to check for the error.</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">Thus you can use plain if=
.. No need for try-catch</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">I.e.</span><o:p></o:p></p=
>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">future<T> f() {</sp=
an><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> auto x=
=3D await f1();</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> auto y=
=3D await WrapErrorWithExpected(f2(x));</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> if (y.=
has_error())
</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> &=
nbsp; return DoSomething();</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> else</=
span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> =
return g(x,y);</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D">}</span><o:p></o:p></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;font-family:"Ca=
libri","sans-serif";color:#1F497D"> </span><o:p></o:p><=
/p>
</blockquote>
<p class=3D"MsoNormal" style=3D"margin-bottom:12.0pt">This is the same as r=
eturning optional<T> directly, which impose to make use of operator*(=
). I don't see the interest of the nesting.<br>
Could you come back to the OP example?<br>
My do-catch suggestion has the advantage to don't need to dereference the r=
esult and probably been more efficient than using exceptions.<br>
<br>
It is very similar to the Haskell do-notation for MonadError<o:p></o:p></p>
<pre>do { action1; action2; action3 } `catchError` handler<o:p></o:p></pre>
<p class=3D"MsoNormal"><br>
<br>
Vicente <br>
<br>
<br>
<o:p></o:p></p>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<div style=3D"border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in =
0in 0in">
<p class=3D"MsoNormal"><b><span style=3D"font-size:11.0pt;font-family:"=
;Calibri","sans-serif";color:windowtext">From:</span></b><sp=
an style=3D"font-size:11.0pt;font-family:"Calibri","sans-ser=
if";color:windowtext"> Vicente J. Botet Escriba [<a href=3D"mailto:vic=
ente.botet@wanadoo.fr">mailto:vicente.botet@wanadoo.fr</a>]
<br>
<b>Sent:</b> Wednesday, November 12, 2014 2:30 PM<br>
<b>To:</b> <a href=3D"mailto:std-proposals@isocpp.org">std-proposals@isocpp=
..org</a>; Gor Nishanov<br>
<b>Subject:</b> Re: [std-proposals] Re: Range-based if versus - await do-ca=
tch statement</span><o:p></o:p></p>
</div>
</div>
<p class=3D"MsoNormal"> <o:p></o:p></p>
<div>
<p class=3D"MsoNormal">Le 11/11/14 22:34, Matthew Woehlke a =C3=A9crit =
;:<o:p></o:p></p>
</div>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<pre>On 2014-11-11 16:12, Brent Friedman wrote:<o:p></o:p></pre>
<blockquote style=3D"margin-top:5.0pt;margin-bottom:5.0pt">
<pre>I've noted in our codebase that we lean heavily on the convenience of<=
o:p></o:p></pre>
<pre>range-based for even when it's not perhaps the best way to express an =
idea.<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>//do something to the first item<o:p></o:p></pre>
<pre>for (auto& Item : range)<o:p></o:p></pre>
<pre>{<o:p></o:p></pre>
<pre> DoSomething(Item);<o:p></o:p></pre>
<pre> break;<o:p></o:p></pre>
<pre>}<o:p></o:p></pre>
</blockquote>
<pre> <o:p></o:p></pre>
<pre> auto first_or_null(auto range) -> decltype(&=
range.begin())<o:p></o:p></pre>
<pre> {<o:p></o:p></pre>
<pre> auto begin =3D range.begin(=
);<o:p></o:p></pre>
<pre> auto end =3D range.end();<o=
:p></o:p></pre>
<pre> return (begin =3D=3D end ? =
nullptr : &(*begin));<o:p></o:p></pre>
<pre> }<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre> if (auto item =3D first_or_null(range))<o:p></o:p><=
/pre>
<pre> <o:p></o:p></pre>
<pre>Basically you want that, right? :-)<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre>I'm not sure if that actually works, and it requires an additional<o:p=
></o:p></pre>
<pre>dereference when you go to use 'item', but OTOH it wouldn't require a<=
o:p></o:p></pre>
<pre>language change...<o:p></o:p></pre>
<pre> <o:p></o:p></pre>
<pre> <o:p></o:p></pre>
</blockquote>
<p class=3D"MsoNormal" style=3D"margin-bottom:12.0pt">If the result of firs=
t_or_null (why not optional<T&>) is configured with
<b>await</b>, would the following be a good syntax for you?<br>
<br>
<b>do</b> { <br>
auto& item =3D <b>await</b> first_or_nul=
l(range)) ;<br>
DoSomething(item);<br>
} <b>catch</b> (...) { // if there is no such element<br=
>
// unsuccessful path... <br>
}<br>
<br>
We will need to adapt <b>await</b> to jump to the <b>catch</b> part instead=
of returning from the function if there is no value.<br>
<br>
This is clearly more complex than your original proposal, but it introduces=
a mechanism to catch the await errors, which could be applicable to other =
cases.
<br>
<br>
I have used <b>do</b> instead of <b>try</b> to recall the Haskell do-notati=
on, and because the semantic and the efficiency, while close, would be quit=
e different.
<br>
<br>
Another possibility is to configure directly any range with await<br>
<br>
<b>do</b> { <br>
auto& item =3D <b>await</b> range ;<br>
DoSomething(item);<br>
} <b>catch</b> (...) { // if there is no such first elem=
ent<br>
// unsuccessful path... <br>
}<br>
<br>
The next question is, how would perform the generated code ? Would it be as=
efficient as<o:p></o:p></p>
<div>
<p class=3D"MsoNormal"> if (!std::empty(range)) {<o:p></o:p></p>
</div>
<div>
<p class=3D"MsoNormal"> DoSomething(*begin(range));<br>
} else {<br>
// unsuccessful path... <br>
}<o:p></o:p></p>
</div>
<p class=3D"MsoNormal"><br>
<br>
Gor what do you think?<br>
<br>
Vicente <o:p></o:p></p>
</blockquote>
<p class=3D"MsoNormal"><o:p> </o:p></p>
</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 />
--_000_6e1462b914214c95a4ff7102f53a9755BL2PR03MB337namprd03pro_--
.