220 27124 <6baa5cbb-e26d-42c5-929c-50c98a716d1a@isocpp.org> article
Path: news.gmane.org!not-for-mail
From: szollosi.lorand@gmail.com
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: for ... else
Date: Sun, 17 Jul 2016 09:40:26 -0700 (PDT)
Lines: 278
Approved: news@gmane.org
Message-ID: <6baa5cbb-e26d-42c5-929c-50c98a716d1a@isocpp.org>
References: <4c0e87f0-5b39-4922-8028-671fd50361b6@isocpp.org>
 <fafc85ca-a102-448e-88e3-c7bd0a0af5af@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_3392_1449707165.1468773626730"
X-Trace: ger.gmane.org 1468773640 8641 80.91.229.3 (17 Jul 2016 16:40:40 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Sun, 17 Jul 2016 16:40:40 +0000 (UTC)
Cc: szollosi.lorand@gmail.com
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDR7PROGSALRB7HJV26AKGQEUZ5WSOA@isocpp.org Sun Jul 17 18:40:36 2016
Return-path: <std-proposals+bncBDR7PROGSALRB7HJV26AKGQEUZ5WSOA@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-io0-f197.google.com ([209.85.223.197])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDR7PROGSALRB7HJV26AKGQEUZ5WSOA@isocpp.org>)
	id 1bOp7G-0001aU-60
	for gclcip-std-proposals@m.gmane.org; Sun, 17 Jul 2016 18:40:30 +0200
Original-Received: by mail-io0-f197.google.com with SMTP id q83sf317802855iod.2
        for <gclcip-std-proposals@m.gmane.org>; Sun, 17 Jul 2016 09:40:29 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=vQ8/qe4KK1v8DLHzS6gyqGRh8yjYp1wc0fvqerjfCfM=;
        b=Wel09pkZJV2azMH/AY0+iPnE/VB32qZ18aPO7iNDHCaTpyyE4vvv/W54U3aAZ/CNAG
         qiC0w0Qoc16qub94x0j9CVm+yzHQTv3qCEL19wa+SWZpYZHv6goks6U1ngjjiLKmStG5
         1H2L2uCUtkHbpVKwjVXZJ74/Xh2aNMzIAXijRrxAI4QuPtSqfxVn2u7Y5bjKdoTQbM3A
         mOGDOey3/DPB0/g0GkqP4yWu+xoVT7P+FrXwDuzMRJyzo1MkvaRpDjTUL5m1OMfrFcBC
         lLAAu3l4LfNbWeDy0RTHx/VGFIZb8OsIFpo7FBJED40N5Q46J1EGSmDU3fAp4arft5Si
         ELTA==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=vQ8/qe4KK1v8DLHzS6gyqGRh8yjYp1wc0fvqerjfCfM=;
        b=n4ae1YJOzg/A+JL42BpMqw3HkMLuBQ5gV8ntZQHkiPi85FBqNDLwgS4/Vgf6jc2rmh
         xfI+v9ieIZtWqM800kNa2HfDSgLx/ONCkZzFI6TWVMrWXjzUEENhIGLJGkjrJFzpHbeO
         OlB15WK/gy7K0wbeDoSoIdwkGJaTneiyv/DEhUQJxJ79PoM4h+C7oC497ySGwVyDLoUs
         iwdahfS3+/3PDhFTRSD3xyZqtNrsKYW0KzA2HsTyNURq9RDWysPj03w6dLKB4zTBPbTj
         1RUUPQ9xFpTRgafdcxpImWDDTtDSwYXCl/wvD1hHWLQRK0NPbeBP4gnFjiKsyA3lppbW
         zFsA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:date:from:to:cc:message-id:in-reply-to
         :references:subject:mime-version:x-original-sender:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=vQ8/qe4KK1v8DLHzS6gyqGRh8yjYp1wc0fvqerjfCfM=;
        b=J5+3fS5dC5G0lHr+F7H2S0Wc3hKAo++tjwjJdKr8XPxG75YVG/pYXjXuJSIPIl/l/U
         pZtiDTmmTyB7KmHkzNswCkZWcuGZqV8zJuJAt+hZAYc1GypMrkSjnH4e81YQs6VX8WFh
         MY66Yl7qm19ifICweQzSF550qAcmmgsaFaF44VTndx7cXhj6dz/DnyEQN6CIs7xuT5pJ
         Z9htmgylDNvCKMYttSThqsp1cggHl0VTSru/y2ujyZzmyQ9Nqb/nsnc2gEhLEORM/8KX
         66ax3gHt3ek6TalQLRJhtLCUVatNqnWEd/7pfcy56D7r///7J3FfYwHk6jjgQ7zRrhcP
         W0IA==
X-Gm-Message-State: ALyK8tLVBCXmBJPae32YEn71MAdZ2YARlSZd7XT+eUHpJY0ghGrxouCtrjSbgOoX/dfTGQ==
X-Received: by 10.157.26.2 with SMTP id a2mr24960106ote.44.1468773628977;
        Sun, 17 Jul 2016 09:40:28 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.36.64.69 with SMTP id n66ls2257360ita.6.gmail; Sun, 17 Jul
 2016 09:40:27 -0700 (PDT)
X-Received: by 10.36.53.200 with SMTP id k191mr1920575ita.9.1468773627841;
        Sun, 17 Jul 2016 09:40:27 -0700 (PDT)
In-Reply-To: <fafc85ca-a102-448e-88e3-c7bd0a0af5af@isocpp.org>
X-Original-Sender: szollosi.lorand@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:27124
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/27124>

------=_Part_3392_1449707165.1468773626730
Content-Type: multipart/alternative; 
	boundary="----=_Part_3393_882063207.1468773626731"

------=_Part_3393_882063207.1468773626731
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

You're perfectly right - in fact, I didn't think about this, sorry.=20
Breaking existing code is a no-go, so we've got three options:

   - define a new keyword (elsefor? when?), which is rarely done;
   - overload another keyword (catch?), this time using a syntax that=20
   allows the compiler to tell the difference between a for-catch and a=20
   try-catch;
   - specifically resolve this by disallowing for loop having else branch=
=20
   when it's the only command in a non-bracketed if. Or, equivalently, havi=
ng=20
   if-else more 'vexing' than for-else. This is somewhat more complicated t=
o=20
   specify but resolves the ambiguity.

As for the break-based else, it solves a somewhat different issue, but that=
=20
might also be useful. In fact, I like that idea very much (the way we work=
=20
around it, i.e., what it'd save us, is a lambda - let alone function - that=
=20
returns inside the loop and has fallback logic after the loop) - it's far=
=20
from confusing, esp. in C++, when you're used to try-catch blocks. Perhaps=
=20
a 'when(break 0) {}` and `when(0) {}` (or catch similarly) syntax could=20
handle both. This is very similar to exceptions but it's way faster - in=20
fact, given proper compiler support and inlining, it requires no additional=
=20
instructions executed, just the jump addresses changed. In fact, there's no=
=20
reason why we should restrict ourselves to only one of these.

To summarize, we might come up with:

for(*init*;* cond*; *incr*)
    *body*
catch(break[0])
    *body-no-break-executed*
catch([0])




*    body-not-executedand, similarly,*for(* init *:* range *)

*    body*catch(break[0])
    *body-no-break-executed*
catch([0])
    *body-not-executed*

What do you think?

2016. j=C3=BAlius 17., vas=C3=A1rnap 16:49:15 UTC+2 id=C5=91pontban Jared G=
rubb a=20
k=C3=B6vetkez=C5=91t =C3=ADrta:
>
> On Sunday, July 17, 2016 at 10:38:12 AM UTC-4, lorro (lo...@lorro.hu=20
> <javascript:>) wrote:
>>
>> Many cases, specific handling is required when the body of the for loop=
=20
>> was not executed. These include variable initializations which would've=
=20
>> gotten value inside the loop, or throwing exceptions. Currently, these=
=20
>> either need double-checking, which is inefficient, or copying the=20
>> condition, which is error-prone, like:
>>
>> {
>>     *init;*
>>     if(*cond*)
>>         do
>>         {
>>             *body*
>>             incr;
>>         } while(*cond*)
>>     else
>>         *body-not-executed*
>> }
>>
>> Note that this is still not exactly what we wanted as variables declared=
=20
>> in init are still visible in else branch. Any alternative requires=20
>> double-checking or introducing a boolean variable that's updated in init=
=20
>> and incr. What I'd recommend instead is allowing an else after for:
>>
>> for(*init*;* cond*; *incr*)
>>     *body*
>> else
>>    =20
>>
>>
>>
>> *body-not-executedor,*for(* init *:* range *)
>>
>> *    body*else
>>     *body-not-executed*
>>
>> As expected, body-not-executed should run iff cond has failed for the=20
>> first time (or range was empty); in other words, if body was not execute=
d.=20
>> Optimizing compilers can unroll this easily and generate optimal code.=
=20
>> Also, it does not clash with other language features as else is currentl=
y=20
>> only allowed after an if.=20
>> What do you think?
>>
>
> Python has a construct like what you describe, but the 'else' body is=20
> executed if the range is empty or [the difference] if the range is iterat=
ed=20
> to exhaustion; in other words, the 'else' clause is executed unless an=20
> instance of the loop calls 'break'.
>
> I personally really like this construct in Python because it makes some=
=20
> constructs easier to write. However, it seems that most people find it mo=
re=20
> confusing than it's worth and wish it had been named something different.
>
> However, I will point out that your proposal would break existing code;=
=20
> for example:
>
> if (cond)=20
>   for (...) {}
> else // does this else match the for or if?
>   bar();
>

--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/6baa5cbb-e26d-42c5-929c-50c98a716d1a%40isocpp.or=
g.

------=_Part_3393_882063207.1468773626731
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">You&#39;re perfectly right - in fact, I didn&#39;t think a=
bout this, sorry. Breaking existing code is a no-go, so we&#39;ve got three=
 options:<br><ul><li>define a new keyword (elsefor? when?), which is rarely=
 done;</li><li>overload another keyword (catch?), this time using a syntax =
that allows the compiler to tell the difference between a for-catch and a t=
ry-catch;<br></li><li>specifically resolve this by disallowing for loop hav=
ing else branch when it&#39;s the only command in a non-bracketed if. Or, e=
quivalently, having if-else more &#39;vexing&#39; than for-else. This is so=
mewhat more complicated to specify but resolves the ambiguity.</li></ul><p>=
As for the break-based else, it solves a somewhat different issue, but that=
 might also be useful. In fact, I like that idea very much (the way we work=
 around it, i.e., what it&#39;d save us, is a lambda - let alone function -=
 that returns inside the loop and has fallback logic after the loop) - it&#=
39;s far from confusing, esp. in C++, when you&#39;re used to try-catch blo=
cks. Perhaps a &#39;when(break 0) {}` and `when(0) {}` (or catch similarly)=
 syntax could handle both. This is very similar to exceptions but it&#39;s =
way faster - in fact, given proper compiler support and inlining, it requir=
es no additional instructions executed, just the jump addresses changed. In=
 fact, there&#39;s no reason why we should restrict ourselves to only one o=
f these.<br></p><br>To summarize, we might come up with:<br><br><span style=
=3D"font-family:courier new,monospace"><span style=3D"font-family:arial,san=
s-serif"><font face=3D"courier new,monospace">for(<i>init</i>;<i> cond</i>;=
 <i>incr</i>)<br>=C2=A0=C2=A0=C2=A0 <i>body</i><br>catch(break[0])<br>=C2=
=A0=C2=A0=C2=A0 <i>body-no-break-executed</i></font></span></span><br><span=
 style=3D"font-family:courier new,monospace"><span style=3D"font-family:ari=
al,sans-serif"><font face=3D"courier new,monospace"><span style=3D"font-fam=
ily:courier new,monospace"><span style=3D"font-family:arial,sans-serif"><fo=
nt face=3D"courier new,monospace">catch([0])</font></span></span><i><span s=
tyle=3D"font-family:courier new,monospace"><span style=3D"font-family:arial=
,sans-serif"><font face=3D"courier new,monospace"><br>=C2=A0=C2=A0=C2=A0 <i=
>body-not-executed<br><br></i></font></span></span><font face=3D"arial,sans=
-serif">and, similarly,<br><br></font></i><font face=3D"arial,sans-serif"><=
font face=3D"courier new,monospace">for(</font></font><i><font face=3D"aria=
l,sans-serif"><font face=3D"courier new,monospace"> init </font></font></i>=
<font face=3D"arial,sans-serif"><font face=3D"courier new,monospace">:</fon=
t></font><i><font face=3D"arial,sans-serif"><font face=3D"courier new,monos=
pace"> range </font></font></i><font face=3D"arial,sans-serif"><font face=
=3D"courier new,monospace">)</font></font><i><font face=3D"arial,sans-serif=
"><font face=3D"courier new,monospace"><br>=C2=A0=C2=A0=C2=A0 body<br></fon=
t></font></i><font face=3D"arial,sans-serif"><font face=3D"courier new,mono=
space">catch(break[0])<br>=C2=A0=C2=A0=C2=A0 <i>body-no-break-executed</i><=
br>catch([0])<br>=C2=A0=C2=A0=C2=A0 </font></font></font></span></span><spa=
n style=3D"font-family:courier new,monospace"><span style=3D"font-family:ar=
ial,sans-serif"><font face=3D"courier new,monospace"><i><span style=3D"font=
-family:courier new,monospace"><span style=3D"font-family:arial,sans-serif"=
><font face=3D"courier new,monospace"><i>body-not-executed</i></font></span=
></span></i></font></span></span><br><br>What do you think?<br><br>2016. j=
=C3=BAlius 17., vas=C3=A1rnap 16:49:15 UTC+2 id=C5=91pontban Jared Grubb a =
k=C3=B6vetkez=C5=91t =C3=ADrta:<blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr">On Sunday, July 17, 2016 at 10:38:12 AM UTC-4, lorro (<a =
href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"1mp167I1DAA=
J" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&#39;;return=
 true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true;">lo...@lo=
rro.hu</a>) wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
Many cases, specific handling is required when the body of the for loop was=
 not executed. These include variable initializations which would&#39;ve go=
tten value inside the loop, or throwing exceptions. Currently, these either=
 need double-checking, which is inefficient, or copying the condition, whic=
h is error-prone, like:<br><span style=3D"font-family:courier new,monospace=
"><br>{<br>=C2=A0=C2=A0=C2=A0 <i>init;</i><br>=C2=A0=C2=A0=C2=A0 if(<i>cond=
</i>)<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 do<br>=C2=A0 =C2=A0=C2=
=A0 =C2=A0=C2=A0 {<br>=C2=A0=C2=A0=C2=A0 =C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 <=
i>body</i><br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 incr;<br>=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 } while(<i>cond</i>)<br>=
=C2=A0=C2=A0=C2=A0 else<br>=C2=A0 =C2=A0=C2=A0 =C2=A0=C2=A0 <i>body-not-exe=
cuted</i><br>}<br><br><span style=3D"font-family:arial,sans-serif">Note tha=
t this is still not exactly what we wanted as variables declared in init ar=
e still visible in else branch. Any alternative requires double-checking or=
 introducing a boolean variable that&#39;s updated in init and incr. What I=
&#39;d recommend instead is allowing an else after for:<br><br><font face=
=3D"courier new,monospace">for(<i>init</i>;<i> cond</i>; <i>incr</i>)<br>=
=C2=A0=C2=A0=C2=A0 <i>body</i><br>else<br>=C2=A0=C2=A0=C2=A0 <i>body-not-ex=
ecuted<br><br><font face=3D"arial,sans-serif">or,<br><br></font></i><font f=
ace=3D"arial,sans-serif"><font face=3D"courier new,monospace">for(</font></=
font><i><font face=3D"arial,sans-serif"><font face=3D"courier new,monospace=
"> init </font></font></i><font face=3D"arial,sans-serif"><font face=3D"cou=
rier new,monospace">:</font></font><i><font face=3D"arial,sans-serif"><font=
 face=3D"courier new,monospace"> range </font></font></i><font face=3D"aria=
l,sans-serif"><font face=3D"courier new,monospace">)</font></font><i><font =
face=3D"arial,sans-serif"><font face=3D"courier new,monospace"><br>=C2=A0=
=C2=A0=C2=A0 body<br></font></font></i><font face=3D"arial,sans-serif"><fon=
t face=3D"courier new,monospace">else<br>=C2=A0=C2=A0=C2=A0 <i>body-not-exe=
cuted</i><br></font></font><i><font face=3D"arial,sans-serif"><font face=3D=
"courier new,monospace"></font></font><br></i><span style=3D"font-family:ar=
ial,sans-serif">As expected, body-not-executed should run iff cond has fail=
ed for the first time (or range was empty); in other words, if body was not=
 executed. Optimizing compilers can unroll this easily and generate optimal=
 code. Also, it does not clash with other language features as else is curr=
ently only allowed after an if. <br>What do you think?<br></span></font></s=
pan></span></div></blockquote><div><br>Python has a construct like what you=
 describe, but the &#39;else&#39; body is executed if the range is empty or=
 [the difference] if the range is iterated to exhaustion; in other words, t=
he &#39;else&#39; clause is executed unless an instance of the loop calls &=
#39;break&#39;.<br><br>I personally really like this construct in Python be=
cause it makes some constructs easier to write. However, it seems that most=
 people find it more confusing than it&#39;s worth and wish it had been nam=
ed something different.<br><br>However, I will point out that your proposal=
 would break existing code; for example:<br><br>if (cond) <br>=C2=A0 for (.=
...) {}<br>else  // does this else match the for or if?<br>=C2=A0 bar();<br>=
</div></div></blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/6baa5cbb-e26d-42c5-929c-50c98a716d1a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6baa5cbb-e26d-42c5-929c-50c98a716d1a=
%40isocpp.org</a>.<br />

------=_Part_3393_882063207.1468773626731--

------=_Part_3392_1449707165.1468773626730--

.
