Topic: Re: [std-proposals] Tersest Lambdas - N3560++ (Propo
Author: Zhihao Yuan <zy@miator.net>
Date: Fri, 12 Dec 2014 11:21:56 -0500
Raw View
On Fri, Dec 12, 2014 at 11:03 AM, Kizza George Mbidde
<kizza.mbidde@gmail.com> wrote:
>
> [&] obj.execute(?) // default: pass by value? Or pass by =E2=80=9Cconst &=
=E2=80=9D? //
> [&] obj.execute(const &?) // explicit pass by const & //
> [&] obj.execute(&?) // pass by non-const ref //
> [&] obj.execute(&&?) // pass by rval ref //
>
> [&] obj.execute(...) // pass all args by default convention //
> [&] obj.execute(?...) // pass all args by default convention //
> [&] obj.execute(const &?...) // pass all args by const & //
> [&] obj.execute(&?...) // pass all args by non-const ref //
> [&] obj.execute(&&?...) // pass all args by rval ref //
>
> [=3D] ptr->execute(?, ?, ?) // pass 3 args, bound by strict position //
> [=3D] ptr->execute(?2, ?1, ?3) // pass 3 args by flexible position, exact=
ly
> like std::bind=E2=80=99s _1, _2, _3 //
> [=3D] ptr->execute(3?, 2?, 1? ) // pass 3 args by flexible position, exac=
tly
> like std::bind=E2=80=99s _1, _2, _3 //
>
just
[&] obj.execute
And perfect forward all arguments seems enough to me.
Further more, instead of using mem_fn, or adding INVOKE to
all STL algorithms, I'd like to have a language feature:
[].member_variable
[].member_function( ... )
--=20
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://bit.ly/blog4bsd
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sat, 13 Dec 2014 18:33:04 +0100
Raw View
This is a multi-part message in MIME format.
--------------020702010602040901030104
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 12/12/14 17:03, Kizza George Mbidde a =C3=A9crit :
> Good afternoon.
>
> The omission of the proposed lambda features in*/=E2=80=9CN3560 - Proposa=
l for=20
> Assorted Extensions to Lambda Expressions=E2=80=9D/* is my only regret wi=
th=20
> the new C++14 updated standard, especially section 2.2. Below, I=20
> present, in hope of getting your feedback, an even terser syntax for=20
> lambdas.
>
> */=E2=80=9CAn Eiffel Tutorial, ISE Technical Report TR-EI-66/TU=E2=80=9D,=
/* chapter 11=20
> (page 92), presents the =E2=80=9Cagents=E2=80=9D feature in Eiffel, which=
is similar=20
> in spirit to lambdas in C++. In particular, the sections titled =E2=80=9C=
Open=20
> and closed arguments=E2=80=9D (page 95) and =E2=80=9COpen targets=E2=80=
=9D (page 97) present a=20
> very elegant & terse syntax for partial function application, or=20
> currying, for which C++ utilizes std::bind;
>
> Given an instantiated object, */root/* in our example, of a class that=20
> has a procedure named */execute/*, Eiffel permits the following;
>
> tasks.do_all( agent root.execute(?) ) //actual Eiffel call for this=20
> would be ( agent root.execute )
> The equivalent C++ code is;
> boost::for_each( tasks, std::bind(&Task::execute, std::ref(root), _1 );
>
> The */=E2=80=9C?=E2=80=9D/* above is a placeholder for whatever argument =
will be=20
> passed as the lambda=E2=80=99s/closure=E2=80=99s single parameter. This s=
yntax is very=20
> terse & elegant.
>
> Section 2.2 of */=E2=80=9CN3560 - Proposal for Assorted Extensions to Lam=
bda=20
> Expressions=E2=80=9D/* already suggested a terse syntax for C++ lambdas;
>
> [&](const auto& e) root.execute(e)
>
> Why not introduce a syntax similar in spirit to the Eiffel syntax? Why=20
> do we need to enforce that */(const auto& e)/* section of code? In=20
> light of the Eiffel syntax, this would be the C++ equivalent;
>
> [&] root.execute(?)
>
> I am no complier writer by leaps & bounds, but I would like, no, love=20
> to believe that the above syntax is possible in C++. Take the calls below=
;
>
> // I use boost.range algorithms cause they support ranges, which we=20
> need in the standard too //
>
> boost::for_each( tasks, [&](const auto& task){ root.execute(task); } );
>
> boost::generate( accounts, [=3D](const auto& acc){ return=20
> ptr->create(acc); } );
>
> boost::for_each(engines_v12, engines_v10,
> [](const auto& v12, const auto& v10)
> {
> ignite(v12, v10);
> }
> );
>
> The above three calls would become;
>
> boost::for_each( tasks, [&] root.execute(?) );
> boost::generate( accounts, [=3D] ptr->create(?) );
> boost::for_each(engines_v12, enginesv_10, [] ignite(?, ?) );
>
I would prefer to be a little bit more explicit without been cumbersome.=20
IMHO, the use of placeholders as ?, _, ?1; _1 doesn't helps to much to=20
the readability. Only the position of the argument is expressed. Using=20
names for the parameters lets more freedom to the user.
boost::for_each( tasks, [&](a) root.execute(a) );
boost::generate( accounts, [=3D](a) ptr->create(a) );
boost::for_each(engines_v12, enginesv_10, [](a,b) ignite(a, b) );
boost::for_each( tasks, [&](a) root.execute(a) );
would be equivalent to
boost::for_each( tasks, [&](auto a) { return root.execute(a) } );
>
>
> Other possible combinations are as below;
>
> [&] obj.execute(?) // default: pass by value? Or pass by =E2=80=9Cconst &=
=E2=80=9D? //
> [&] obj.execute(const &?) // explicit pass by const & //
> [&] obj.execute(&?) // pass by non-const ref //
> [&] obj.execute(&&?) // pass by rval ref //
>
[&](a) obj.execute(a) // default: pass by value? Or pass by =E2=80=9Cconst =
&=E2=80=9D? //
[&](const& a) obj.execute(a) // explicit pass by const & //
[&](& a) obj.execute(a) // pass by non-const ref //
[&](&& a) obj.execute(a) // pass by rval ref //
>
>
> [&] obj.execute(...) // pass all args by default convention //
>
[&](...a) obj.execute(a...) // pass all args by default convention //
....
>
> [&] obj.execute(?...) // pass all args by default convention //
> [&] obj.execute(const &?...) // pass all args by const & //
> [&] obj.execute(&?...) // pass all args by non-const ref //
> [&] obj.execute(&&?...) // pass all args by rval ref //
>
> [=3D] ptr->execute(?, ?, ?) // pass 3 args, bound by strict position //
> [=3D] ptr->execute(?2, ?1, ?3) // pass 3 args by flexible position,=20
> exactly like std::bind=E2=80=99s _1, _2, _3 //
> [=3D] ptr->execute(3?, 2?, 1? ) // pass 3 args by flexible position,=20
> exactly like std::bind=E2=80=99s _1, _2, _3 //
>
[=3D](a,b,c) ptr->execute(a, b, c) // pass 3 args, bound by strict position=
//
[=3D](a,b,c) ptr->execute(b, a, c) // pass 3 args by flexible position,=20
exactly like std::bind=E2=80=99s _1, _2, _3 //
....
> Please give me your thoughts & feedback on this very terse lambda syntax.
>
Anyway, if you want to explore more the placeholder approach, I find the=20
use of &, && and const& on the call side counter intuitive
[&] obj.execute(const &?...) // pass all args by const & //
You could be even more terse. Instead of
boost::for_each( tasks, [&] root.execute(?) );
why not let the compiler deduce a lambda with the correct closure and=20
parameter types from an expression having placeholders as "?" ;-)
boost::for_each( tasks, root.execute(?) );
The deduction of the closure and the parameters would work only if there=20
is only one match, the closure will include any variable in the scope=20
used on the expression and the kind of parameter &, && const& (volatile)=20
will be deduced from this single match.
I don't know how this could manage with multiple statements as suggested=20
by Scott, as there is no function to match :(
|
std::for_each(xs.begin(),xs.end(),// can I have multiple statements?
{std::cout <<(?)<<std::endl;
(?)++;}
);
|
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/.
--------------020702010602040901030104
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 12/12/14 17:03, Kizza George Mbidde
a =C3=A9crit=C2=A0:<br>
</div>
<blockquote
cite=3D"mid:3cd87fb6-5e56-4ca2-96e3-89a536c6d70f@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div><font face=3D"georgia,serif"><font size=3D"4">Good afternoon.<=
br>
=C2=A0<br>
The omission of the proposed lambda features in<strong><em>
=E2=80=9CN3560 - Proposal for Assorted Extensions to Lamb=
da
Expressions=E2=80=9D</em></strong> is my only regret with=
the
new C++14 updated standard, especially section 2.2. Below,
I present, in hope of getting your feedback, an even
terser syntax for lambdas.<br>
=C2=A0<br>
<strong><em>=E2=80=9CAn Eiffel Tutorial, ISE Technical Report
TR-EI-66/TU=E2=80=9D,</em></strong> chapter 11 (page 92),
presents the =E2=80=9Cagents=E2=80=9D feature in Eiffel, whic=
h is similar
in spirit to lambdas in C++. In particular, the sections
titled =E2=80=9COpen and closed arguments=E2=80=9D (page 95) =
and =E2=80=9COpen
targets=E2=80=9D (page 97) present a very elegant & terse
syntax for partial function application, or currying, for
which C++ utilizes std::bind;<br>
=C2=A0<br>
Given an instantiated object, <strong><em>root</em></strong>
in our example, of a class that has a procedure named <strong=
><em>execute</em></strong>,
Eiffel permits the following;<br>
=C2=A0<br>
<font color=3D"#0000ff">tasks.do_all( agent root.execute(?)
) </font><font color=3D"#274e13">//actual Eiffel call for
this would be ( agent root.execute )</font></font></font></=
div>
<div>=C2=A0</div>
<div><font size=3D"4" face=3D"georgia,serif">The equivalent C++ cod=
e
is;</font></div>
<div>=C2=A0</div>
<div><font face=3D"georgia,serif"><font size=3D"4"><font
color=3D"#0000ff">boost::for_each( tasks,
std::bind(&Task::execute, std::ref(root), _1 );<br>
</font>=C2=A0<br>
The <strong><em>=E2=80=9C?=E2=80=9D</em></strong> above is a =
placeholder
for whatever argument will be passed as the
lambda=E2=80=99s/closure=E2=80=99s single parameter. This syn=
tax is very
terse & elegant.<br>
=C2=A0<br>
Section 2.2 of <strong><em>=E2=80=9CN3560 - Proposal for Asso=
rted
Extensions to Lambda Expressions=E2=80=9D</em></strong>
already suggested a terse syntax for C++ lambdas;<br>
=C2=A0<br>
</font><font size=3D"4"><font color=3D"#0000ff">[&](const
auto& e) root.execute(e)<br>
</font>=C2=A0<br>
Why not introduce a syntax similar in spirit to the Eiffel
syntax? Why do we need to enforce that <strong><em>(const
auto& e)</em></strong> section of code? In light
of the Eiffel syntax, this would be the C++ equivalent;<br>
=C2=A0<br>
</font><font size=3D"4"><font color=3D"#0000ff">[&]
root.execute(?)<br>
</font>=C2=A0<br>
I am no complier writer by leaps & bounds, but I would
like, no, love to believe that the above syntax is
possible in C++. Take the calls below;<br>
=C2=A0<br>
<font color=3D"#274e13">// I use boost.range algorithms
cause they support ranges, which we need in the standard
too //</font></font></font></div>
<div>=C2=A0</div>
<p><font size=3D"4" color=3D"#0000ff" face=3D"georgia,serif">boost:=
:for_each(
tasks, [&](const auto& task){ root.execute(task); }
);</font></p>
<p><font face=3D"georgia,serif"><font size=3D"4"><font
color=3D"#0000ff">boost::generate( accounts, [=3D](const
auto& acc){ return ptr->create(acc); } );<br>
=C2=A0<br>
boost::for_each(engines_v12, engines_v10,<br>
=C2=A0 [](const auto& v12, const auto& v10)<br>
=C2=A0 {<br>
=C2=A0=C2=A0=C2=A0 ignite(v12, v10);<br>
=C2=A0 }<br>
);<br>
</font>=C2=A0<br>
The above three calls would become;<br>
=C2=A0<br>
</font><font size=3D"4"><font color=3D"#0000ff">boost::for_each=
(
tasks, [&] root.execute(?) );<br>
boost::generate( accounts, [=3D] ptr->create(?) );<br>
boost::for_each(engines_v12, enginesv_10, [] ignite(?,
?) );<br>
</font>=C2=A0<br>
</font></font></p>
</div>
</blockquote>
<font size=3D"4"><font face=3D"georgia,serif">I would prefer to be a
little bit more explicit without been cumbersome</font></font>.
IMHO, the use of placeholders as ?, _, ?1; _1 doesn't helps to much
to the readability. Only the position of the argument is expressed.
Using names for the parameters lets more freedom to the user.=C2=A0 <br=
>
<br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">b=
oost::for_each(
tasks, [&](a) root.execute(a) );<br>
boost::generate( accounts, [=3D](a) ptr->create(a) );<br>
boost::for_each(engines_v12, enginesv_10, [](a,b) ignite(a, b)
);<br>
</font></font></font><br>
<br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">b=
oost::for_each(
tasks, [&](a) root.execute(a) );<br>
</font></font></font><br>
would be equivalent to <br>
<br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">b=
oost::for_each(
tasks, [&](auto a) { return root.execute(a) } );<br>
</font></font></font><br>
<blockquote
cite=3D"mid:3cd87fb6-5e56-4ca2-96e3-89a536c6d70f@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<p><font face=3D"georgia,serif"><font size=3D"4"><font
color=3D"#0000ff"><br>
</font>=C2=A0<br>
Other possible combinations are as below;<br>
=C2=A0<br>
</font><font size=3D"4"><font color=3D"#0000ff">[&]
obj.execute(?) <font color=3D"#274e13">// default: pass
by value? Or pass by =E2=80=9Cconst &=E2=80=9D? //<br=
>
</font>[&] obj.execute(const &?) <font
color=3D"#274e13">// explicit pass by const & //<br>
</font>[&] obj.execute(&?) <font
color=3D"#274e13">// pass by non-const ref //<br>
</font>[&] obj.execute(&&?) <font
color=3D"#274e13">// pass by rval ref //<br>
</font></font></font></font></p>
</div>
</blockquote>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
&](a)
obj.execute(a) <font color=3D"#274e13">// default: pass by
value? Or pass by =E2=80=9Cconst &=E2=80=9D? //<br>
</font>[&](const& a) obj.execute(a) <font
color=3D"#274e13">// explicit pass by const & //<br>
</font>[&](& a) obj.execute(a) <font color=3D"#274e13">//
pass by non-const ref //<br>
</font>[&](&& a) obj.execute(a) <font
color=3D"#274e13">// pass by rval ref //<br>
</font></font></font></font>
<blockquote
cite=3D"mid:3cd87fb6-5e56-4ca2-96e3-89a536c6d70f@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<p><font face=3D"georgia,serif"><font size=3D"4"><font
color=3D"#0000ff">=C2=A0<br>
[&] obj.execute(...) <font color=3D"#274e13">// pass
all args by default convention //<br>
</font></font></font></font></p>
</div>
</blockquote>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
&](...a)
obj.execute(a...) <font color=3D"#274e13">// pass all args by
default convention //<br>
...<br>
</font></font></font></font>
<blockquote
cite=3D"mid:3cd87fb6-5e56-4ca2-96e3-89a536c6d70f@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<p><font face=3D"georgia,serif"><font size=3D"4"><font
color=3D"#0000ff">[&] obj.execute(?...) <font
color=3D"#274e13">// pass all args by default convention
//<br>
</font>[&] obj.execute(const &?...) <font
color=3D"#274e13">// pass all args by const & //<br>
</font>[&] obj.execute(&?...) <font
color=3D"#274e13">// pass all args by non-const ref //<br=
>
</font>[&] obj.execute(&&?...) <font
color=3D"#274e13">// pass all args by rval ref //<br>
</font>=C2=A0<br>
[=3D] ptr->execute(?, ?, ?) <font color=3D"#274e13">//
pass 3 args, bound by strict position //<br>
</font>[=3D] ptr->execute(?2, ?1, ?3) <font
color=3D"#274e13">// pass 3 args by flexible position,
exactly like std::bind=E2=80=99s _1, _2, _3 //<br>
</font>[=3D] ptr->execute(3?, 2?, 1? ) <font
color=3D"#274e13">// pass 3 args by flexible position,
exactly like std::bind=E2=80=99s _1, _2, _3 //<br>
</font></font></font></font></p>
</div>
</blockquote>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
=3D](a,b,c)
ptr->execute(a, b, c) <font color=3D"#274e13">// pass 3
args, bound by strict position //<br>
</font>[=3D](a,b,c) ptr->execute(b, a, c) <font
color=3D"#274e13">// pass 3 args by flexible position, exactly
like std::bind=E2=80=99s _1, _2, _3 //</font></font></font></fo=
nt> <br>
...<br>
<br>
<br>
<blockquote
cite=3D"mid:3cd87fb6-5e56-4ca2-96e3-89a536c6d70f@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<p><font face=3D"georgia,serif"><font size=3D"4">Please give me you=
r
thoughts & feedback on this very terse lambda syntax.<br>
=C2=A0</font></font><br>
</p>
</div>
</blockquote>
<br>
Anyway, if you want to explore more the placeholder approach, I find
the use of &, && and const& on the call side counter
intuitive=C2=A0 <br>
<br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
&]
obj.execute(const &?...) <font color=3D"#274e13">// pass
all args by const & //<br>
<br>
<br>
</font></font></font></font>You could be even more terse.
Instead of<br>
<font face=3D"georgia,serif"><font size=3D"4">=C2=A0<br>
</font><font size=3D"4"><font color=3D"#0000ff">boost::for_each(
tasks, [&] root.execute(?) );<br>
<br>
</font></font></font>why not let the compiler deduce a lambda
with the correct closure and parameter types from an expression
having placeholders as "?"=C2=A0 ;-) <br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff"><=
br>
boost::for_each( tasks, root.execute(?) );<br>
</font></font></font><br>
The deduction of the closure and the parameters would work only if
there is only one match, the closure will include any variable in
the scope used on the expression and the kind of parameter &,
&& const& (volatile) will be deduced from this single
match.<br>
<br>
I don't know how this could manage with multiple statements as
suggested by Scott, as there is no function to match :( <br>
<br>
<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); word-wrap: break-word; background-color: rgb(250, 250,
250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #000;"
class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 std</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">::</span><span style=3D"color:
#000;" class=3D"styled-by-prettify">for_each</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify">xs</span><s=
pan
style=3D"color: #660;" class=3D"styled-by-prettify">.</span><sp=
an
style=3D"color: #008;" class=3D"styled-by-prettify">begin</span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify">(),</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"> xs</span><=
span
style=3D"color: #660;" class=3D"styled-by-prettify">.</span><sp=
an
style=3D"color: #008;" class=3D"styled-by-prettify">end</span><=
span
style=3D"color: #660;" class=3D"styled-by-prettify">(),</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
style=3D"color: #800;" class=3D"styled-by-prettify">// can I
have multiple statements?</span><span style=3D"color: #000;"
class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">{</span><span style=3D"color:
#000;" class=3D"styled-by-prettify"> std</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan
style=3D"color: #000;" class=3D"styled-by-prettify">cout </span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
style=3D"color: #660;" class=3D"styled-by-prettify">(?)</span><=
span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
style=3D"color: #660;" class=3D"styled-by-prettify"><<</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"> std</span>=
<span
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan
style=3D"color: #000;" class=3D"styled-by-prettify">endl</span>=
<span
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"=
color: #000;"
class=3D"styled-by-prettify"> </span><span style=3D"color:
#660;" class=3D"styled-by-prettify">(?)++;</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
style=3D"color: #660;" class=3D"styled-by-prettify">}</span><sp=
an
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0 </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">);</span></div>
</code></div>
<br>
<br>
Vicente<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------020702010602040901030104--
.
Author: Kizza George Mbidde <kizza.mbidde@gmail.com>
Date: Sat, 13 Dec 2014 13:48:12 -0800 (PST)
Raw View
------=_Part_1652_801524379.1418507292966
Content-Type: multipart/alternative;
boundary="----=_Part_1653_55320222.1418507292966"
------=_Part_1653_55320222.1418507292966
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Thank you for your feedback Vicente; it has been valuable.
On Saturday, December 13, 2014 8:33:07 PM UTC+3, Vicente J. Botet Escriba=
=20
wrote:
>
> Le 12/12/14 17:03, Kizza George Mbidde a =C3=A9crit :
> =20
> Good afternoon.
> =20
> The omission of the proposed lambda features in* =E2=80=9CN3560 - Proposa=
l for=20
> Assorted Extensions to Lambda Expressions=E2=80=9D* is my only regret wit=
h the=20
> new C++14 updated standard, especially section 2.2. Below, I present, in=
=20
> hope of getting your feedback, an even terser syntax for lambdas.
> =20
> *=E2=80=9CAn Eiffel Tutorial, ISE Technical Report TR-EI-66/TU=E2=80=9D,*=
chapter 11=20
> (page 92), presents the =E2=80=9Cagents=E2=80=9D feature in Eiffel, which=
is similar in=20
> spirit to lambdas in C++. In particular, the sections titled =E2=80=9COpe=
n and=20
> closed arguments=E2=80=9D (page 95) and =E2=80=9COpen targets=E2=80=9D (p=
age 97) present a very=20
> elegant & terse syntax for partial function application, or currying, for=
=20
> which C++ utilizes std::bind;
> =20
> Given an instantiated object, *root* in our example, of a class that has=
=20
> a procedure named *execute*, Eiffel permits the following;
> =20
> tasks.do_all( agent root.execute(?) ) //actual Eiffel call for this would=
=20
> be ( agent root.execute )
> =20
> The equivalent C++ code is;
> =20
> boost::for_each( tasks, std::bind(&Task::execute, std::ref(root), _1 );
> =20
> The *=E2=80=9C?=E2=80=9D* above is a placeholder for whatever argument wi=
ll be passed as=20
> the lambda=E2=80=99s/closure=E2=80=99s single parameter. This syntax is v=
ery terse &=20
> elegant.
> =20
> Section 2.2 of *=E2=80=9CN3560 - Proposal for Assorted Extensions to Lamb=
da=20
> Expressions=E2=80=9D* already suggested a terse syntax for C++ lambdas;
> =20
> [&](const auto& e) root.execute(e)
> =20
> Why not introduce a syntax similar in spirit to the Eiffel syntax? Why do=
=20
> we need to enforce that *(const auto& e)* section of code? In light of=20
> the Eiffel syntax, this would be the C++ equivalent;
> =20
> [&] root.execute(?)
> =20
> I am no complier writer by leaps & bounds, but I would like, no, love to=
=20
> believe that the above syntax is possible in C++. Take the calls below;
> =20
> // I use boost.range algorithms cause they support ranges, which we need=
=20
> in the standard too //
> =20
>
> boost::for_each( tasks, [&](const auto& task){ root.execute(task); } );
>
> boost::generate( accounts, [=3D](const auto& acc){ return ptr->create(acc=
);=20
> } );
> =20
> boost::for_each(engines_v12, engines_v10,
> [](const auto& v12, const auto& v10)
> {
> ignite(v12, v10);
> }
> );
> =20
> The above three calls would become;
> =20
> boost::for_each( tasks, [&] root.execute(?) );
> boost::generate( accounts, [=3D] ptr->create(?) );
> boost::for_each(engines_v12, enginesv_10, [] ignite(?, ?) );
> =20
> =20
> I would prefer to be a little bit more explicit without been cumbersome.=
=20
> IMHO, the use of placeholders as ?, _, ?1; _1 doesn't helps to much to th=
e=20
> readability. Only the position of the argument is expressed. Using names=
=20
> for the parameters lets more freedom to the user. =20
>
> boost::for_each( tasks, [&](a) root.execute(a) );
> boost::generate( accounts, [=3D](a) ptr->create(a) );
> boost::for_each(engines_v12, enginesv_10, [](a,b) ignite(a, b) );
>
>
> boost::for_each( tasks, [&](a) root.execute(a) );
>
> would be equivalent to=20
>
> boost::for_each( tasks, [&](auto a) { return root.execute(a) } );
>
> =20
> =20
> Other possible combinations are as below;
> =20
> [&] obj.execute(?) // default: pass by value? Or pass by =E2=80=9Cconst &=
=E2=80=9D? //
> [&] obj.execute(const &?) // explicit pass by const & //
> [&] obj.execute(&?) // pass by non-const ref //
> [&] obj.execute(&&?) // pass by rval ref //
> =20
> [&](a) obj.execute(a) // default: pass by value? Or pass by =E2=80=9Ccons=
t &=E2=80=9D? //
> [&](const& a) obj.execute(a) // explicit pass by const & //
> [&](& a) obj.execute(a) // pass by non-const ref //
> [&](&& a) obj.execute(a) // pass by rval ref //
> =20
> =20
> [&] obj.execute(...) // pass all args by default convention //
> =20
> [&](...a) obj.execute(a...) // pass all args by default convention //
> ...
> =20
> [&] obj.execute(?...) // pass all args by default convention //
> [&] obj.execute(const &?...) // pass all args by const & //
> [&] obj.execute(&?...) // pass all args by non-const ref //
> [&] obj.execute(&&?...) // pass all args by rval ref //
> =20
> [=3D] ptr->execute(?, ?, ?) // pass 3 args, bound by strict position //
> [=3D] ptr->execute(?2, ?1, ?3) // pass 3 args by flexible position, exact=
ly=20
> like std::bind=E2=80=99s _1, _2, _3 //
> [=3D] ptr->execute(3?, 2?, 1? ) // pass 3 args by flexible position,=20
> exactly like std::bind=E2=80=99s _1, _2, _3 //
> =20
> [=3D](a,b,c) ptr->execute(a, b, c) // pass 3 args, bound by strict positi=
on=20
> //
> [=3D](a,b,c) ptr->execute(b, a, c) // pass 3 args by flexible position,=
=20
> exactly like std::bind=E2=80=99s _1, _2, _3 //=20
> ...
>
>
> Please give me your thoughts & feedback on this very terse lambda syntax=
..
> =20
> =20
>
> Anyway, if you want to explore more the placeholder approach, I find the=
=20
> use of &, && and const& on the call side counter intuitive =20
>
> [&] obj.execute(const &?...) // pass all args by const & //
>
>
> You could be even more terse. Instead of
> =20
> boost::for_each( tasks, [&] root.execute(?) );
>
> why not let the compiler deduce a lambda with the correct closure and=20
> parameter types from an expression having placeholders as "?" ;-)=20
>
> boost::for_each( tasks, root.execute(?) );
>
> The deduction of the closure and the parameters would work only if there=
=20
> is only one match, the closure will include any variable in the scope use=
d=20
> on the expression and the kind of parameter &, && const& (volatile) will =
be=20
> deduced from this single match.
>
> I don't know how this could manage with multiple statements as suggested=
=20
> by Scott, as there is no function to match :(=20
>
>
> =20
> std::for_each(xs.begin(), xs.end(), // can I have multiple statements=
?
> { std::cout << (?) << std::endl;
> (?)++; }
> );
> =20
>
> Vicente
> =20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1653_55320222.1418507292966
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><font size=3D"4"><span style=3D"font-family: georgia,serif=
;">Thank you for your feedback Vicente; it has been valuable.</span></font>=
<br><br>On Saturday, December 13, 2014 8:33:07 PM UTC+3, Vicente J. Botet E=
scriba wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>Le 12/12/14 17:03, Kizza George Mbidde
a =C3=A9crit :<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<div><font face=3D"georgia,serif"><font size=3D"4">Good afternoon.<=
br>
<br>
The omission of the proposed lambda features in<b><i>
=E2=80=9CN3560 - Proposal for Assorted Extensions to Lamb=
da
Expressions=E2=80=9D</i></b> is my only regret with the
new C++14 updated standard, especially section 2.2. Below,
I present, in hope of getting your feedback, an even
terser syntax for lambdas.<br>
<br>
<b><i>=E2=80=9CAn Eiffel Tutorial, ISE Technical Report
TR-EI-66/TU=E2=80=9D,</i></b> chapter 11 (page 92),
presents the =E2=80=9Cagents=E2=80=9D feature in Eiffel, whic=
h is similar
in spirit to lambdas in C++. In particular, the sections
titled =E2=80=9COpen and closed arguments=E2=80=9D (page 95) =
and =E2=80=9COpen
targets=E2=80=9D (page 97) present a very elegant & terse
syntax for partial function application, or currying, for
which C++ utilizes std::bind;<br>
<br>
Given an instantiated object, <b><i>root</i></b>
in our example, of a class that has a procedure named <b><i>e=
xecute</i></b>,
Eiffel permits the following;<br>
<br>
<font color=3D"#0000ff">tasks.do_all( agent root.execute(?)
) </font><font color=3D"#274e13">//actual Eiffel call for
this would be ( agent root.execute )</font></font></font></=
div>
<div> </div>
<div><font face=3D"georgia,serif" size=3D"4">The equivalent C++ cod=
e
is;</font></div>
<div> </div>
<div><font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#=
0000ff">boost::for_each( tasks,
std::bind(&Task::execute, std::ref(root), _1 );<br>
</font> <br>
The <b><i>=E2=80=9C?=E2=80=9D</i></b> above is a placeholder
for whatever argument will be passed as the
lambda=E2=80=99s/closure=E2=80=99s single parameter. This syn=
tax is very
terse & elegant.<br>
<br>
Section 2.2 of <b><i>=E2=80=9CN3560 - Proposal for Assorted
Extensions to Lambda Expressions=E2=80=9D</i></b>
already suggested a terse syntax for C++ lambdas;<br>
<br>
</font><font size=3D"4"><font color=3D"#0000ff">[&](const
auto& e) root.execute(e)<br>
</font> <br>
Why not introduce a syntax similar in spirit to the Eiffel
syntax? Why do we need to enforce that <b><i>(const
auto& e)</i></b> section of code? In light
of the Eiffel syntax, this would be the C++ equivalent;<br>
<br>
</font><font size=3D"4"><font color=3D"#0000ff">[&]
root.execute(?)<br>
</font> <br>
I am no complier writer by leaps & bounds, but I would
like, no, love to believe that the above syntax is
possible in C++. Take the calls below;<br>
<br>
<font color=3D"#274e13">// I use boost.range algorithms
cause they support ranges, which we need in the standard
too //</font></font></font></div>
<div> </div>
<p><font color=3D"#0000ff" face=3D"georgia,serif" size=3D"4">boost:=
:for_each(
tasks, [&](const auto& task){ root.execute(task); }
);</font></p>
<p><font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#00=
00ff">boost::generate( accounts, [=3D](const
auto& acc){ return ptr->create(acc); } );<br>
<br>
boost::for_each(engines_v12, engines_v10,<br>
[](const auto& v12, const auto& v10)<br>
{<br>
ignite(v12, v10);<br>
}<br>
);<br>
</font> <br>
The above three calls would become;<br>
<br>
</font><font size=3D"4"><font color=3D"#0000ff">boost::for_each=
(
tasks, [&] root.execute(?) );<br>
boost::generate( accounts, [=3D] ptr->create(?) );<br>
boost::for_each(engines_v12, enginesv_10, [] ignite(?,
?) );<br>
</font> <br>
</font></font></p>
</div>
</blockquote>
<font size=3D"4"><font face=3D"georgia,serif">I would prefer to be a
little bit more explicit without been cumbersome</font></font>.
IMHO, the use of placeholders as ?, _, ?1; _1 doesn't helps to much
to the readability. Only the position of the argument is expressed.
Using names for the parameters lets more freedom to the user. <br=
>
<br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">b=
oost::for_each(
tasks, [&](a) root.execute(a) );<br>
boost::generate( accounts, [=3D](a) ptr->create(a) );<br>
boost::for_each(engines_v12, enginesv_10, [](a,b) ignite(a, b)
);<br>
</font></font></font><br>
<br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">b=
oost::for_each(
tasks, [&](a) root.execute(a) );<br>
</font></font></font><br>
would be equivalent to <br>
<br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">b=
oost::for_each(
tasks, [&](auto a) { return root.execute(a) } );<br>
</font></font></font><br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<p><font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#00=
00ff"><br>
</font> <br>
Other possible combinations are as below;<br>
<br>
</font><font size=3D"4"><font color=3D"#0000ff">[&]
obj.execute(?) <font color=3D"#274e13">// default: pass
by value? Or pass by =E2=80=9Cconst &=E2=80=9D? //<br=
>
</font>[&] obj.execute(const &?) <font color=3D"#27=
4e13">// explicit pass by const & //<br>
</font>[&] obj.execute(&?) <font color=3D"#274e13">=
// pass by non-const ref //<br>
</font>[&] obj.execute(&&?) <font color=3D"#274=
e13">// pass by rval ref //<br>
</font></font></font></font></p>
</div>
</blockquote>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
&](a)
obj.execute(a) <font color=3D"#274e13">// default: pass by
value? Or pass by =E2=80=9Cconst &=E2=80=9D? //<br>
</font>[&](const& a) obj.execute(a) <font color=3D"#274e1=
3">// explicit pass by const & //<br>
</font>[&](& a) obj.execute(a) <font color=3D"#274e13">//
pass by non-const ref //<br>
</font>[&](&& a) obj.execute(a) <font color=3D"#274e1=
3">// pass by rval ref //<br>
</font></font></font></font>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<p><font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#00=
00ff"> <br>
[&] obj.execute(...) <font color=3D"#274e13">// pass
all args by default convention //<br>
</font></font></font></font></p>
</div>
</blockquote>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
&](...a)
obj.execute(a...) <font color=3D"#274e13">// pass all args by
default convention //<br>
...<br>
</font></font></font></font>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<p><font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#00=
00ff">[&] obj.execute(?...) <font color=3D"#274e13">// pass all args by=
default convention
//<br>
</font>[&] obj.execute(const &?...) <font color=3D"=
#274e13">// pass all args by const & //<br>
</font>[&] obj.execute(&?...) <font color=3D"#274e1=
3">// pass all args by non-const ref //<br>
</font>[&] obj.execute(&&?...) <font color=3D"#=
274e13">// pass all args by rval ref //<br>
</font> <br>
[=3D] ptr->execute(?, ?, ?) <font color=3D"#274e13">//
pass 3 args, bound by strict position //<br>
</font>[=3D] ptr->execute(?2, ?1, ?3) <font color=3D"#27=
4e13">// pass 3 args by flexible position,
exactly like std::bind=E2=80=99s _1, _2, _3 //<br>
</font>[=3D] ptr->execute(3?, 2?, 1? ) <font color=3D"#2=
74e13">// pass 3 args by flexible position,
exactly like std::bind=E2=80=99s _1, _2, _3 //<br>
</font></font></font></font></p>
</div>
</blockquote>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
=3D](a,b,c)
ptr->execute(a, b, c) <font color=3D"#274e13">// pass 3
args, bound by strict position //<br>
</font>[=3D](a,b,c) ptr->execute(b, a, c) <font color=3D"#274e=
13">// pass 3 args by flexible position, exactly
like std::bind=E2=80=99s _1, _2, _3 //</font></font></font></fo=
nt> <br>
...<br>
<br>
<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">
<p><font face=3D"georgia,serif"><font size=3D"4">Please give me you=
r
thoughts & feedback on this very terse lambda syntax.<br>
</font></font><br>
</p>
</div>
</blockquote>
<br>
Anyway, if you want to explore more the placeholder approach, I find
the use of &, && and const& on the call side counter
intuitive <br>
<br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
&]
obj.execute(const &?...) <font color=3D"#274e13">// pass
all args by const & //<br>
<br>
<br>
</font></font></font></font>You could be even more terse.
Instead of<br>
<font face=3D"georgia,serif"><font size=3D"4"> <br>
</font><font size=3D"4"><font color=3D"#0000ff">boost::for_each(
tasks, [&] root.execute(?) );<br>
<br>
</font></font></font>why not let the compiler deduce a lambda
with the correct closure and parameter types from an expression
having placeholders as "?" ;-) <br>
<font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff"><=
br>
boost::for_each( tasks, root.execute(?) );<br>
</font></font></font><br>
The deduction of the closure and the parameters would work only if
there is only one match, the closure will include any variable in
the scope used on the expression and the kind of parameter &,
&& const& (volatile) will be deduced from this single
match.<br>
<br>
I don't know how this could manage with multiple statements as
suggested by Scott, as there is no function to match :( <br>
<br>
<br>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;ba=
ckground-color:rgb(250,250,250)"><code>
<div><span style=3D"color:#000"><br>
std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#000">for_each</span><span style=3D"color:#660">(</span><=
span style=3D"color:#000">xs</span><span style=3D"color:#660">.</span><span=
style=3D"color:#008">begin</span><span style=3D"color:#660">(),</span><spa=
n style=3D"color:#000"> xs</span><span style=3D"color:#660">.</span><span s=
tyle=3D"color:#008">end</span><span style=3D"color:#660">(),</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#800">// can I
have multiple statements?</span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">{=
</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::<=
/span><span style=3D"color:#000">cout </span><span style=3D"color:#660"><=
;<</span><span style=3D"color:#000"> </span><span style=3D"color:#660">(=
?)</span><span style=3D"color:#000"> </span><span style=3D"color:#660"><=
<</span><span style=3D"color:#000"> std</span><span style=3D"color:#660"=
>::</span><span style=3D"color:#000">endl</span><span style=3D"color:#660">=
;</span><span style=3D"color:#000"><br>
</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">(?)++;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">}</span><span style=3D"color=
:#000"><br>
</span><span style=3D"color:#660">);</span></div>
</code></div>
<br>
<br>
Vicente<br>
</div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1653_55320222.1418507292966--
------=_Part_1652_801524379.1418507292966--
.