220 13959 <6d5e0622-29bb-4196-ad7b-9c6b5f08f8cb@isocpp.org> article
Path: news.gmane.org!not-for-mail
From: chris.kohlhoff@gmail.com
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Comment on N4244
Date: Thu, 16 Oct 2014 04:18:09 -0700 (PDT)
Lines: 283
Approved: news@gmane.org
Message-ID: <6d5e0622-29bb-4196-ad7b-9c6b5f08f8cb@isocpp.org>
References: <0632b234-2e7b-489f-a640-aa927648eaf7@isocpp.org>
 <02d9673d-3dd3-4fec-aa7a-b925b73f9893@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; 
	boundary="----=_Part_6312_344266244.1413458290222"
X-Trace: ger.gmane.org 1413458302 32195 80.91.229.3 (16 Oct 2014 11:18:22 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Thu, 16 Oct 2014 11:18:22 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBCS7VEH374ORB46S72QQKGQE3GGVVNI@isocpp.org Thu Oct 16 13:18:14 2014
Return-path: <std-proposals+bncBCS7VEH374ORB46S72QQKGQE3GGVVNI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-yh0-f72.google.com ([209.85.213.72])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBCS7VEH374ORB46S72QQKGQE3GGVVNI@isocpp.org>)
	id 1Xej4P-0003gV-9a
	for gclcip-std-proposals@m.gmane.org; Thu, 16 Oct 2014 13:18:13 +0200
Original-Received: by mail-yh0-f72.google.com with SMTP id a41sf7926416yho.3
        for <gclcip-std-proposals@m.gmane.org>; Thu, 16 Oct 2014 04:18:12 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe
         :content-type;
        bh=nD8Ra3Z/i8RZMaGhfQ9YEeCht9jExsRRaScYtsXtWYI=;
        b=hg15vZ4Pe1Zx5O1kDJoeLot17yY/qcP/ehreqo24Jj3KyoBB5CV0hG3Nq01zdhHLyn
         UhU2nz1QbZbFrdxM8CZSqCyJfhYVpxkCqK9OIrAoq8Lc6yeaAx6irntorKbRsHBR9+HU
         DG1y9WctWFYV2j2uK6Fb0NXviPR9bT3mQ+MRE61gnHQG0kcLmIJUKTxmqFlOmtn5Wggp
         wcKuQxtquCxGu/cvDg9agSkTslnQSeJ7krB60+oVzY9izhzSc2/S7wH2qm4a+Lf4iIyF
         zS27PuoaTCZbiihag8QiWaGvNKdlKuoXHEsrYwmx8kPdWPaFyiAxUDGG/M2S6MOHm/Ee
         Sjcg==
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:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe:content-type;
        bh=nD8Ra3Z/i8RZMaGhfQ9YEeCht9jExsRRaScYtsXtWYI=;
        b=gd188d6YOoYSuj3GEytE6gXWv7iA/zIkMhnlQHdkpCjml1xNRNgelp8c8WklKY9s49
         SLb+XffqIX3iKwAB6QgM6TEcvwYnZx8rCheNxwHXLxO5SvZaNjyuIXR6N3PFydqWGlTV
         4WO+6U2Z+71Le/k8kqr/YL0gxnpWkpXtON5fiRKblgbopipASzAT4l90xeqyyPLZyKFv
         8XaB3AvZcUff8k1nqHrqh+s9xoDnMHZk6ifc33YfA6Zkw4Udoow0DmUEpIS/594ZSQXy
         ehKzLmx+pCjQkdnelPlnRet+E/vNrbifqy5C0390JQVbsL7x9rCCNsqnVROoOdl2Fp1n
         zySA==
X-Gm-Message-State: ALoCoQmM5xT7ZKulOBWdO1aya8u9P6u2mU+9dYVhg6+vvv2nzpFe22F7tbo47U+jzuR0QP7IdOzU
X-Received: by 10.224.128.7 with SMTP id i7mr442546qas.9.1413458292365;
        Thu, 16 Oct 2014 04:18:12 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.107.130.170 with SMTP id m42ls552128ioi.50.gmail; Thu, 16 Oct
 2014 04:18:11 -0700 (PDT)
X-Received: by 10.50.138.66 with SMTP id qo2mr300521igb.7.1413458291776;
        Thu, 16 Oct 2014 04:18:11 -0700 (PDT)
In-Reply-To: <02d9673d-3dd3-4fec-aa7a-b925b73f9893@isocpp.org>
X-Original-Sender: chris.kohlhoff@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://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>,
 <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:13959
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/13959>

------=_Part_6312_344266244.1413458290222
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable



On Thursday, October 16, 2014 7:12:29 PM UTC+11, Giovanni Piero Deretta=20
wrote:
>
>
>
> On Wednesday, October 15, 2014 7:06:38 AM UTC+1, Germ=C3=A1n Diago wrote:
>>
>> Hello everyone,
>>
>> I see the coroutines proposal with language integration and it looks=20
>> great.
>>
>> This paper talks about an extension.
>>
>>
>> While in previous papers resumable functions were annoted with resumable=
,=20
>> it is not the case anymore.
>> The function will be resumable if there is "yield" or "await" inside it.
>>
>> Why would lambdas need the "resumable" annotation then, and don't follow=
=20
>> what the coroutines proposal does?
>>
>>
> a vote for N4244 from me as well: another great paper from Christopher=20
> Kohlhoff.
>

Thanks!=20

I never liked resumable functions as described in N3977, the runtime=20
> overhead required to implement that spec is completely superfluous. Also=
=20
> using futures for coroutine results seems wrong: futures are for=20
> asynchronous operations, coroutines/generators themselves are inherently=
=20
> synchronous (although a common use case is to bring order to async ops).
>
> Regarding N4244 itself, just a couple of comments:
>
> * as you already pointed out, the resumable annotation seems superfluous=
=20
> as the 'resumableness' can be inferred by the presence of yield in the bo=
dy.
>

Technically I agree, however there were a few reasons why I chose to keep=
=20
it in.

- The name "yield" is already being used as a function and variable name=20
(including in the standard library). Not being a compiler writer, I'm not=
=20
sure how much effort it is to make the keyword context sensitive, so I=20
chose to be conservative.

- We already have mutable lambdas denoted by a keyword, and a resumable=20
lambda must be mutable too. It felt more consistent and readable to keep a=
=20
keyword in that position, as not having a keyword currently means that the=
=20
lambda is const.

- I had code generators in the back of my mind, such as a tool that=20
simulates reflection and automatically generates serialisation support for=
=20
data structures. In this case the inconsistency in the behaviour of an=20
empty lambda bothered me. With the presence of yield determining whether a=
=20
lambda is resumable, an empty one is just a plain function object and thus=
=20
repeatedly callable. Any side effects in the body will be applied=20
repeatedly. With the proposal as written, an empty lambda still meets the=
=20
generator requirements, and will reach the terminal state after the first=
=20
call, i.e. side effects in the body can only occur once.

However, I am perfectly happy for it to be automatic, but I kept it in so=
=20
others have to explicitly choose to remove it after considering these=20
issues.
=20

> * Drop the yield(type) expression support, and simply allow plain yield=
=20
> (or yield() ) as an expression: the input type should be static the same=
=20
> way the output is: if "yield  1; yield "foo"; " is not legal, neither=20
> should be "auto x =3D yield(int); auto y =3D  yield(char *);". As far as =
I can=20
> tell, yield(type) requires runtime type checking which not only seems an=
=20
> unecessary overhead but can lead to runtime failures. Polymoprhism in the=
=20
> input/output type should be explicit by yielding/receiving the equivalent=
=20
> of a boost::variant, boost::any.
> * I'm not a big fan of the "f.wanted() =3D x" syntax to pass parameters t=
o=20
> the coroutine, I would have preferred the plain "f(x)", but I understand=
=20
> that causes other problems.
>

These two points are kind of related so I'll address them as one, but=20
working backwards.

First, "f(x)" actually works already because the lambda is still a function=
=20
object. The example at the end of section 7 uses this approach.

The "wanted" function on the other hand is needed to support composition of=
=20
sub-generators that return different types (i'm thinking async operations=
=20
here). For example:

  []() resumable
  {
    std::size_t n =3D yield from async_op_returning_a_size();
    std::string s =3D yield from async_op_returning_a_string();
  }

In python the async I/O framework effectively send()s the result of an=20
operation to the generator and it passes it onwards to the innermost=20
sub-generator, but python is also dynamically typed and lets us mix the=20
different generators without further thought. We need some form of dynamic=
=20
typing to do the same in C++, and as this is a core use case of the=20
facility i don't think it would be good to defer the polymorphism to a=20
library type.

In the snippet above, the async_op_returning_a_size() function already=20
"knows" that it wants a size_t result, so there's actually no possibility=
=20
to get the types wrong at runtime. The runtime check is not actually used=
=20
or required in this case. There is also no extra runtime overhead in this=
=20
case because the wanted() of the outer generator already has to forward the=
=20
call to the wanted() of the currently active sub-generator.

However, what I realised after submitting the paper is that the "x =3D yiel=
d=20
(int)" syntax is technically superfluous. You could instead replace it with=
=20
a library type which is itself a generator, e.g. "x =3D yield from=20
want<int>()". The generator returned by want<int>() would look similar to=
=20
the async_read_generator in section 11.

Cheers,
Chris

--=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_6312_344266244.1413458290222
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Thursday, October 16, 2014 7:12:29 PM UTC+11, G=
iovanni Piero Deretta wrote:<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"><br><br>On Wednesday, October 15, 2014 7:06:38 AM UTC+1, Ger=
m=C3=A1n Diago wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r">Hello everyone,<div><br></div><div>I see the coroutines proposal with la=
nguage integration and it looks great.</div><div><br></div><div>This paper =
talks about an extension.</div><div><br></div><div><br></div><div>While in =
previous papers resumable functions were annoted with resumable, it is not =
the case anymore.</div><div>The function will be resumable if there is "yie=
ld" or "await" inside it.</div><div><br></div><div>Why would lambdas need t=
he "resumable" annotation then, and don't follow what the coroutines propos=
al does?</div><div><br></div></div></blockquote><div><br>a vote for N4244 f=
rom me as well: another great paper from Christopher Kohlhoff.<br></div></d=
iv></blockquote><div><br></div><div>Thanks!&nbsp;</div><div><br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>I never liked=
 resumable functions as described in N3977, the runtime overhead required t=
o implement that spec is completely superfluous. Also using futures for cor=
outine results seems wrong: futures are for asynchronous operations, corout=
ines/generators themselves are inherently synchronous (although a common us=
e case is to bring order to async ops).<br><br>Regarding N4244 itself, just=
 a couple of comments:<br><br>* as you already pointed out, the resumable a=
nnotation seems superfluous as the 'resumableness' can be inferred by the p=
resence of yield in the body.<br></div></div></blockquote><div><br></div><d=
iv>Technically I agree, however there were a few reasons why I chose to kee=
p it in.</div><div><br></div><div>- The name "yield" is already being used =
as a function and variable name (including in the standard library). Not be=
ing a compiler writer, I'm not sure how much effort it is to make the keywo=
rd context sensitive, so I chose to be conservative.</div><div><br></div><d=
iv>- We already have mutable lambdas denoted by a keyword, and a resumable =
lambda must be mutable too. It felt more consistent and readable to keep a =
keyword in that position, as not having a keyword currently means that the =
lambda is const.</div><div><br></div><div>- I had code generators in the ba=
ck of my mind, such as a tool that simulates reflection and automatically g=
enerates serialisation support for data structures. In this case the incons=
istency in the behaviour of an empty lambda bothered me. With the presence =
of yield determining whether a lambda is resumable, an empty one is just a =
plain function object and thus repeatedly callable. Any side effects in the=
 body will be applied repeatedly. With the proposal as written, an empty la=
mbda still meets the generator requirements, and will reach the terminal st=
ate after the first call, i.e. side effects in the body can only occur once=
..</div><div><br></div><div>However, I am perfectly happy for it to be autom=
atic, but I kept it in so others have to explicitly choose to remove it aft=
er considering these issues.</div><div>&nbsp;</div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div dir=3D"ltr"><div>* Drop the yield(type) expressio=
n support, and simply allow plain yield (or yield() ) as an expression: the=
 input type should be static the same way the output is: if "yield&nbsp; 1;=
 yield "foo"; " is not legal, neither should be "auto x =3D yield(int); aut=
o y =3D&nbsp; yield(char *);". As far as I can tell, yield(type) requires r=
untime type checking which not only seems an unecessary overhead but can le=
ad to runtime failures. Polymoprhism in the input/output type should be exp=
licit by yielding/receiving the equivalent of a boost::variant, boost::any.=
<br>* I'm not a big fan of the "f.wanted() =3D x" syntax to pass parameters=
 to the coroutine, I would have preferred the plain "f(x)", but I understan=
d that causes other problems.<br></div></div></blockquote><div><br></div><d=
iv>These two points are kind of related so I'll address them as one, but wo=
rking backwards.</div><div><br></div><div>First, "f(x)" actually works alre=
ady because the lambda is still a function object. The example at the end o=
f section 7 uses this approach.</div><div><br></div><div>The "wanted" funct=
ion on the other hand is needed to support composition of sub-generators th=
at return different types (i'm thinking async operations here). For example=
:</div><div><br></div><div>&nbsp; []() resumable</div><div>&nbsp; {</div><d=
iv>&nbsp; &nbsp; std::size_t n =3D yield from async_op_returning_a_size();<=
/div><div>&nbsp; &nbsp; std::string s =3D yield from async_op_returning_a_s=
tring();</div><div>&nbsp; }</div><div><br></div><div>In python the async I/=
O framework effectively send()s the result of an operation to the generator=
 and it passes it onwards to the innermost sub-generator, but python is als=
o dynamically typed and lets us mix the different generators without furthe=
r thought. We need some form of dynamic typing to do the same in C++, and a=
s this is a core use case of the facility i don't think it would be good to=
 defer the polymorphism to a library type.</div><div><br></div><div>In the =
snippet above, the async_op_returning_a_size() function already "knows" tha=
t it wants a size_t result, so there's actually no possibility to get the t=
ypes wrong at runtime. The runtime check is not actually used or required i=
n this case. There is also no extra runtime overhead in this case because t=
he wanted() of the outer generator already has to forward the call to the w=
anted() of the currently active sub-generator.</div><div><br></div><div>How=
ever, what I realised after submitting the paper is that the "x =3D yield (=
int)" syntax is technically superfluous. You could instead replace it with =
a library type which is itself a generator, e.g. "x =3D yield from want&lt;=
int&gt;()". The generator returned by want&lt;int&gt;() would look similar =
to the async_read_generator in section 11.</div><div><br></div><div>Cheers,=
</div><div>Chris</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&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 />
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_6312_344266244.1413458290222--

.
