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 &amp; 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(&amp;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 &amp; 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">[&amp;](const
                auto&amp; 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&amp; 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">[&amp;]
                root.execute(?)<br>
              </font>=C2=A0<br>
              I am no complier writer by leaps &amp; 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, [&amp;](const auto&amp; 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&amp; acc){ return ptr-&gt;create(acc); } );<br>
                =C2=A0<br>
                boost::for_each(engines_v12, engines_v10,<br>
                =C2=A0 [](const auto&amp; v12, const auto&amp; 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, [&amp;] root.execute(?) );<br>
                boost::generate( accounts, [=3D] ptr-&gt;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, [&amp;](a) root.execute(a) );<br>
          boost::generate( accounts, [=3D](a) ptr-&gt;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, [&amp;](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, [&amp;](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">[&amp;]
                obj.execute(?) <font color=3D"#274e13">// default: pass
                  by value? Or pass by =E2=80=9Cconst &amp;=E2=80=9D? //<br=
>
                </font>[&amp;] obj.execute(const &amp;?) <font
                  color=3D"#274e13">// explicit pass by const &amp; //<br>
                </font>[&amp;] obj.execute(&amp;?) <font
                  color=3D"#274e13">// pass by non-const ref //<br>
                </font>[&amp;] obj.execute(&amp;&amp;?) <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">[=
&amp;](a)
          obj.execute(a) <font color=3D"#274e13">// default: pass by
            value? Or pass by =E2=80=9Cconst &amp;=E2=80=9D? //<br>
          </font>[&amp;](const&amp; a) obj.execute(a) <font
            color=3D"#274e13">// explicit pass by const &amp; //<br>
          </font>[&amp;](&amp; a) obj.execute(a) <font color=3D"#274e13">//
            pass by non-const ref //<br>
          </font>[&amp;](&amp;&amp; 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>
                [&amp;] 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">[=
&amp;](...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">[&amp;] obj.execute(?...) <font
                  color=3D"#274e13">// pass all args by default convention
                  //<br>
                </font>[&amp;] obj.execute(const &amp;?...) <font
                  color=3D"#274e13">// pass all args by const &amp; //<br>
                </font>[&amp;] obj.execute(&amp;?...) <font
                  color=3D"#274e13">// pass all args by non-const ref //<br=
>
                </font>[&amp;] obj.execute(&amp;&amp;?...) <font
                  color=3D"#274e13">// pass all args by rval ref //<br>
                </font>=C2=A0<br>
                [=3D] ptr-&gt;execute(?, ?, ?) <font color=3D"#274e13">//
                  pass 3 args, bound by strict position //<br>
                </font>[=3D] ptr-&gt;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-&gt;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-&gt;execute(a, b, c) <font color=3D"#274e13">// pass 3
            args, bound by strict position //<br>
          </font>[=3D](a,b,c) ptr-&gt;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 &amp; 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 &amp;, &amp;&amp; and const&amp; on the call side counter
    intuitive=C2=A0 <br>
    <br>
    <font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
&amp;]
          obj.execute(const &amp;?...) <font color=3D"#274e13">// pass
            all args by const &amp; //<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, [&amp;] 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 &amp;,
    &amp;&amp; const&amp; (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">&lt;&lt;</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">&lt;&lt;</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&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 />

--------------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&nbsp;:<br>
    </div>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div><font face=3D"georgia,serif"><font size=3D"4">Good afternoon.<=
br>
              &nbsp;<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>
              &nbsp;<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 &amp; terse
              syntax for partial function application, or currying, for
              which C++ utilizes std::bind;<br>
              &nbsp;<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>
              &nbsp;<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>&nbsp;</div>
        <div><font face=3D"georgia,serif" size=3D"4">The equivalent C++ cod=
e
            is;</font></div>
        <div>&nbsp;</div>
        <div><font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#=
0000ff">boost::for_each( tasks,
                std::bind(&amp;Task::execute, std::ref(root), _1 );<br>
              </font>&nbsp;<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 &amp; elegant.<br>
              &nbsp;<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>
              &nbsp;<br>
            </font><font size=3D"4"><font color=3D"#0000ff">[&amp;](const
                auto&amp; e) root.execute(e)<br>
              </font>&nbsp;<br>
              Why not introduce a syntax similar in spirit to the Eiffel
              syntax? Why do we need to enforce that <b><i>(const
                  auto&amp; e)</i></b> section of code? In light
              of the Eiffel syntax, this would be the C++ equivalent;<br>
              &nbsp;<br>
            </font><font size=3D"4"><font color=3D"#0000ff">[&amp;]
                root.execute(?)<br>
              </font>&nbsp;<br>
              I am no complier writer by leaps &amp; bounds, but I would
              like, no, love to believe that the above syntax is
              possible in C++. Take the calls below;<br>
              &nbsp;<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>&nbsp;</div>
        <p><font color=3D"#0000ff" face=3D"georgia,serif" size=3D"4">boost:=
:for_each(
            tasks, [&amp;](const auto&amp; 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&amp; acc){ return ptr-&gt;create(acc); } );<br>
                &nbsp;<br>
                boost::for_each(engines_v12, engines_v10,<br>
                &nbsp; [](const auto&amp; v12, const auto&amp; v10)<br>
                &nbsp; {<br>
                &nbsp;&nbsp;&nbsp; ignite(v12, v10);<br>
                &nbsp; }<br>
                );<br>
              </font>&nbsp;<br>
              The above three calls would become;<br>
              &nbsp;<br>
            </font><font size=3D"4"><font color=3D"#0000ff">boost::for_each=
(
                tasks, [&amp;] root.execute(?) );<br>
                boost::generate( accounts, [=3D] ptr-&gt;create(?) );<br>
                boost::for_each(engines_v12, enginesv_10, [] ignite(?,
                ?) );<br>
              </font>&nbsp;<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.&nbsp; <br=
>
    <br>
    <font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">b=
oost::for_each(
          tasks, [&amp;](a) root.execute(a) );<br>
          boost::generate( accounts, [=3D](a) ptr-&gt;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, [&amp;](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, [&amp;](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>&nbsp;<br>
              Other possible combinations are as below;<br>
              &nbsp;<br>
            </font><font size=3D"4"><font color=3D"#0000ff">[&amp;]
                obj.execute(?) <font color=3D"#274e13">// default: pass
                  by value? Or pass by =E2=80=9Cconst &amp;=E2=80=9D? //<br=
>
                </font>[&amp;] obj.execute(const &amp;?) <font color=3D"#27=
4e13">// explicit pass by const &amp; //<br>
                </font>[&amp;] obj.execute(&amp;?) <font color=3D"#274e13">=
// pass by non-const ref //<br>
                </font>[&amp;] obj.execute(&amp;&amp;?) <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">[=
&amp;](a)
          obj.execute(a) <font color=3D"#274e13">// default: pass by
            value? Or pass by =E2=80=9Cconst &amp;=E2=80=9D? //<br>
          </font>[&amp;](const&amp; a) obj.execute(a) <font color=3D"#274e1=
3">// explicit pass by const &amp; //<br>
          </font>[&amp;](&amp; a) obj.execute(a) <font color=3D"#274e13">//
            pass by non-const ref //<br>
          </font>[&amp;](&amp;&amp; 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">&nbsp;<br>
                [&amp;] 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">[=
&amp;](...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">[&amp;] obj.execute(?...) <font color=3D"#274e13">// pass all args by=
 default convention
                  //<br>
                </font>[&amp;] obj.execute(const &amp;?...) <font color=3D"=
#274e13">// pass all args by const &amp; //<br>
                </font>[&amp;] obj.execute(&amp;?...) <font color=3D"#274e1=
3">// pass all args by non-const ref //<br>
                </font>[&amp;] obj.execute(&amp;&amp;?...) <font color=3D"#=
274e13">// pass all args by rval ref //<br>
                </font>&nbsp;<br>
                [=3D] ptr-&gt;execute(?, ?, ?) <font color=3D"#274e13">//
                  pass 3 args, bound by strict position //<br>
                </font>[=3D] ptr-&gt;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-&gt;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-&gt;execute(a, b, c) <font color=3D"#274e13">// pass 3
            args, bound by strict position //<br>
          </font>[=3D](a,b,c) ptr-&gt;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 &amp; feedback on this very terse lambda syntax.<br>
              &nbsp;</font></font><br>
        </p>
      </div>
    </blockquote>
    <br>
    Anyway, if you want to explore more the placeholder approach, I find
    the use of &amp;, &amp;&amp; and const&amp; on the call side counter
    intuitive&nbsp; <br>
    <br>
    <font face=3D"georgia,serif"><font size=3D"4"><font color=3D"#0000ff">[=
&amp;]
          obj.execute(const &amp;?...) <font color=3D"#274e13">// pass
            all args by const &amp; //<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">&nbsp;<br>
      </font><font size=3D"4"><font color=3D"#0000ff">boost::for_each(
          tasks, [&amp;] 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 "?"&nbsp; ;-) <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 &amp;,
    &amp;&amp; const&amp; (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>
            &nbsp; &nbsp; 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>
            &nbsp; &nbsp; &nbsp; &nbsp; </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">&lt=
;&lt;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">(=
?)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&lt;=
&lt;</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>
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</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>
            &nbsp; &nbsp; </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&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_1653_55320222.1418507292966--
------=_Part_1652_801524379.1418507292966--

.