An implementation of Generic lambdas (Request for feedback)

1,263 views
Skip to first unread message

Faisal Vali

unread,
Dec 17, 2012, 2:05:37 PM12/17/12
to std-dis...@isocpp.org, std-pr...@isocpp.org
Motivated by the positive feedback we received regarding Generic
Lambdas (during the October 2012 ISO C++ Standards Meeting in
Portland), I have implemented a reasonably complete (unless I am
missing something obvious) implementation
(http://faisalv.github.com/clang-glambda/) of most of the proposal
(named lambda syntax for functions has not been attempted) using a
fork of clang.

We would like to encourage developers who are interested in this
feature, to either compile the code or download the binaries (sorry,
only windows for now) and play with the implementation and provide us
with feedback so that we can incorporate it within our next revision
of the document.

The following link: http://faisalv.github.com/clang-glambda/, has some
instructions (towards the bottom) on how to compile the code or use
the binaries for windows.

Any and all constructive feedback will be greatly appreciated.

The current version (12/2012) implements subproposals 2.1, 2.2, 2.3 and 2.5.

2.1 Allow the type-specifier within a parameter declaration of a
lambda to be auto (i.e. auto is mandatory)

auto Sum = [](auto a, decltype(a) b) { return a + b; };
int i = Sum(3, 4);
double d = Sum(3.14, 2.77);

2.2 Allow the use of familiar template syntax in lambda expressions

auto NumElements = []<int N>(auto (&a)[N]) { return N; };
int arri[]{1, 2, 3};
double arrd[]{3.14, 2.77, 6.626};
auto total = NumElements(arri) + NumElements(arrd);

2.3 Permit a lambda body to be an expression

int local = 10;
auto L = [&](auto a) a + ++local;

2.5 Autogenerate a conversion to function pointer in captureless generic lambdas

auto L = [](auto a, decltype(a) b) { return a + b; };
int (*fp)(int, int) = L;


Thank you and looking forward to the feedback!

dain...@gmail.com

unread,
Dec 17, 2012, 5:38:25 PM12/17/12
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com
Cool :)

 Why is "auto" required though? It seems like it would work fine without the keyword..?


Andrew Sandoval

unread,
Dec 18, 2012, 12:18:30 AM12/18/12
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com
That looks great!  What is the status of the proposal?

As soon as time permits I plan to test out the implementation.

Thanks,
Andrew Sandoval

tra...@solidfire.com

unread,
Dec 18, 2012, 10:50:50 AM12/18/12
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com, dain...@gmail.com
The `auto` is required is disambiguate this:

[] (a) {}

Is `a` an automatically-typed variable or an unnamed argument with the type `a`?

iba...@gmail.com

unread,
Dec 19, 2012, 4:45:36 PM12/19/12
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com, dain...@gmail.com

[] (a) {}

Is `a` an automatically-typed variable or an unnamed argument with the type `a`?

Isn't this another case of - if it can be a typename it is a typename? 

Fernando Cacciola

unread,
Dec 19, 2012, 9:41:15 PM12/19/12
to std-pr...@isocpp.org
On Tue, Dec 18, 2012 at 12:50 PM, <tra...@solidfire.com> wrote:
> The `auto` is required is disambiguate this:
>
> [] (a) {}
>
> Is `a` an automatically-typed variable or an unnamed argument with the type
> `a`?
>
Really?

Not according to the relevant paper:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf

Where it specifically says that auto is NOT allowed (not just not
required), which necessarily disallows unnamed parameters precisely to
avoid the ambiguity.

Has this changed? I like it better without auto FWIW

Best

Travis Gockel

unread,
Dec 20, 2012, 11:35:41 AM12/20/12
to std-pr...@isocpp.org
Not according to the relevant paper: 

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf

Where it specifically says that auto is NOT allowed (not just not
required), which necessarily disallows unnamed parameters precisely to
avoid the ambiguity.

Has this changed? I like it better without auto FWIW

Hasn't changed, just didn't realize that caveat: "A consequence of this decision is that generic lambdas do not support unnamed parameters." 

Herb Sutter

unread,
Dec 20, 2012, 12:59:18 PM12/20/12
to std-pr...@isocpp.org

Note that this proposal is still in progress, and is changing based on EWG input.

 

In particular, in Portland there was considerable concern from Bjarne in particular about the “overly terse” form, such as []( &a ) as a synonym for []( auto& a ), mainly on the grounds that:

·         If we adopt concept-like template constraints in the future we want to write things like []( iterator a ) and allowing dropping the ‘auto’ now potentially could make people lazy and disincentivized to insert the concept/constraint name in the future.

·         As noted, it means we can’t have unnamed parameters for lambdas, which for better or worse are allowed everywhere else and so would be inconsistent with the rest of the language.

 

I still think there’s real demand for the terse form that doesn’t require ‘auto’, but there is a design tension here that we’re still working out.

 

Herb

 

 

--
 
 
 

Scott Prager

unread,
Dec 20, 2012, 1:16:18 PM12/20/12
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com
Absolutely fantastic! A few things on interest:

I had not realized this syntax supports nesting:

auto compose = []( auto f, auto g )
   
[=]( auto x ) f( g(x) );

auto curry3 =
   
[]( auto f )
       
[=](auto x) [=](auto y) [=](auto z)
           f
(x,y,z);

And variadic lambdas, too! Very nice.
But I wonder why we couldn't...

auto f = []( auto _f ) [](auto ...x) _f(x...);

I wrote some tests. A few lines caused the compiler to crash so I commented them out and labelled them "Crash!".

https://gist.github.com/4347130

Fernando Cacciola

unread,
Dec 20, 2012, 1:38:11 PM12/20/12
to std-pr...@isocpp.org
On Thu, Dec 20, 2012 at 2:59 PM, Herb Sutter <hsu...@microsoft.com> wrote:
> Note that this proposal is still in progress, and is changing based on EWG
> input.
>
>
>
> In particular, in Portland there was considerable concern from Bjarne in
> particular about the “overly terse” form, such as []( &a ) as a synonym for
> []( auto& a ), mainly on the grounds that:
>
> · If we adopt concept-like template constraints in the future we
> want to write things like []( iterator a ) and allowing dropping the ‘auto’
> now potentially could make people lazy and disincentivized to insert the
> concept/constraint name in the future.
>
I see.

When auto was being initially discussed in c.l.cpp.m, I mentioned that

f( auto a, auto b, auto c, auto d )

was lexically the same as

f(a, b, c, d)

i.e., the auto keyword doesn't really add any information, and that I
preferred something like

f( T a, T b, U c, X d );

instead.

My reason was that even though the parameters are fully typed, the
types are lexically lost, which might be a problem, specially when
maintaining f().

In my own example, 'a' and 'b' are declared to be of the same type
which would not necessarily be the case in the "unconstrained" case of
(auto a, auto b,....), so it was clear that I might want to give the
type a name, but I might also want to explicitly not do so. Hence I
realized that 'auto' as a "whatever type specifier" serves it's
purpose, and let go of the idea.

Now I see that some of that is still in the air. Sometimes you want to
explicitely indicate that any type is just fine, sometimes you want to
explicitly name it so you can express things that relate to the type.
For instance, that a group of parameters shall be of the same type: X
a, X b, Y c, or that the actual type is a derivation: shared_ptr<T>,
or as in your example, that the type must satisfy certain requirements
(i.e. be a concept)

I believe that (a) we sometimes want to name the type, while (b)
sometimes we don't, being that a deliberate design decision. The
current state of the proposal addresses that by allowing you to omit
the type-specifier (case a) or naming the type via the familiar
template syntax (case b)

IMO, requiring, or even allowing auto is like having case (a) but
looking like case (b), which IMHO would be a mistake and would add
nothing. What I think we need is to support both cases cleanly and
consistently (and the current paper does that)

(FWIW, I would prefer a simpler syntax where you can say (T a) instead
of <class T>(T a), but that's a lot more difficult given the current
language definition)

Best














--
Fernando Cacciola
SciSoft Consulting, Founder
http://www.scisoft-consulting.com

Fernando Cacciola

unread,
Dec 20, 2012, 1:58:29 PM12/20/12
to std-pr...@isocpp.org
On Thu, Dec 20, 2012 at 3:59 PM, Herb Sutter <hsu...@microsoft.com> wrote:

> In particular, in Portland there was considerable concern from Bjarne in
> particular

I realize now that it might be be clear from my last response how that
addresses the specific concerns mentioned.

> about the “overly terse” form, such as []( &a ) as a synonym for
> []( auto& a ), mainly on the grounds that:
>
> · If we adopt concept-like template constraints in the future we
> want to write things like []( iterator a )

From my POV:

You would type [](& a) when you *explicitly* express that there are
no requirement on the type of a. Which is what you do if you use auto.

And you would type [](iterator a) (or [](T a, T b as another example),
when express the requirements.

So IMO both are separate design choices, hence I wouldn't consider
using auto for the first one just to be "lexically closer" to the
second one.
In the long term, it would much more annoy everyone for having to
write auto for no real purpose than it would help lazy programmers
(who better don't work in C++) do the right thing.

Nevin Liber

unread,
Dec 20, 2012, 2:34:16 PM12/20/12
to std-pr...@isocpp.org
On 20 December 2012 12:38, Fernando Cacciola <fernando...@gmail.com> wrote:

f(a, b, c, d)

i.e., the auto keyword doesn't really add any information, and that I
preferred something like

f( T a, T b, U c, X d );

But if any of those types T, U or X happen to exist and come into view (say, by including a header), you've changed the meaning.  That seems very error prone to me.

I once had to debug a template problem caused by a 3rd party doing

#define U8 unsigned char

so it does happen, even with short names.

IMO, requiring, or even allowing auto is like having case (a)  but
looking like case (b), which IMHO would be a mistake and would add
nothing.

Not putting auto in *already* has a meaning; it is perfectly legal to write:

[](string){}

Changing string to mean "parameter" instead of "type" is a breaking change from C++11 and inconsistent with the rest of the language.
 
(FWIW, I would prefer a simpler syntax where you can say (T a) instead
of <class T>(T a), but that's a lot more difficult given the current
language definition)

Again, I think that is incredibly error prone, because its meaning changes based on whether or not T is a lexically available type.
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

Fernando Cacciola

unread,
Dec 20, 2012, 2:44:42 PM12/20/12
to std-pr...@isocpp.org
On Thu, Dec 20, 2012 at 5:34 PM, Nevin Liber <ne...@eviloverlord.com> wrote:
> On 20 December 2012 12:38, Fernando Cacciola <fernando...@gmail.com>
> wrote:
>>
>>
>> f(a, b, c, d)
>>
>> i.e., the auto keyword doesn't really add any information, and that I
>> preferred something like
>>
>> f( T a, T b, U c, X d );
>
>
> But if any of those types T, U or X happen to exist and come into view (say,
> by including a header), you've changed the meaning. That seems very error
> prone to me.
>
> I once had to debug a template problem caused by a 3rd party doing
>
> #define U8 unsigned char
>
> so it does happen, even with short names.
>
Right.
I didn't consider that too much back then, but now in the context of
the proposal the first think I noticed is that they propose to use the
familiar template syntax.

You'd type <class T>[]( T& a) instead of just [](T& a)

so that shouldn't be a problem

(and regarding what I said about dropping <class T>, you are right and
I did think of it, that's why I just mentioned that I liked that but
it's not currently possible)


>> IMO, requiring, or even allowing auto is like having case (a) but
>> looking like case (b), which IMHO would be a mistake and would add
>> nothing.
>
>
> Not putting auto in *already* has a meaning; it is perfectly legal to write:
>
> [](string){}
>
> Changing string to mean "parameter" instead of "type" is a breaking change
> from C++11 and inconsistent with the rest of the language.
>

OK.
Now this is a different argument. You have a point, but, I would say
that the solution is simple: disallow unnamed parameters (like they do
in the proposal)

>>
>> (FWIW, I would prefer a simpler syntax where you can say (T a) instead
>> of <class T>(T a), but that's a lot more difficult given the current
>> language definition)
>
>
> Again, I think that is incredibly error prone, because its meaning changes
> based on whether or not T is a lexically available type.

Are you referring to the case when you'd use <class T>?

If so, why? It's the exact same thing as with an ordinary function
template and that's never been a problem.

Nevin Liber

unread,
Dec 20, 2012, 3:07:07 PM12/20/12
to std-pr...@isocpp.org
On 20 December 2012 13:44, Fernando Cacciola <fernando...@gmail.com> wrote:

> Not putting auto in *already* has a meaning; it is perfectly legal to write:
>
> [](string){}
>
> Changing string to mean "parameter" instead of "type" is a breaking change
> from C++11 and inconsistent with the rest of the language.
>

OK.
Now this is a different argument. You have a point, but, I would say
that the solution is simple: disallow unnamed parameters (like they do
in the proposal)

I don't see how this fixes the problem; it is still a breaking change, making it far less likely to pass for C++14.  Take the following example:

struct Missiles
{
    Missiles(int numberToCreate) { /*... */ }
    Missiles& operator()(int numberToLaunch) { /* ... */ }
};

[](Missiles){ return Missiles(1); }

This behavior has changed silently under the proposal.
 
>> (FWIW, I would prefer a simpler syntax where you can say (T a) instead
>> of <class T>(T a), but that's a lot more difficult given the current
>> language definition)
>
>
> Again, I think that is incredibly error prone, because its meaning changes
> based on whether or not T is a lexically available type.

Are you referring to the case when you'd use <class T>?

No, omitting the <class T> is the error prone case.  You need something to say what 'T' is.

Herb Sutter

unread,
Dec 20, 2012, 3:09:19 PM12/20/12
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com

Composition and currying are cool.

 

Those who don’t like the terse syntax may object that it’s only slightly worse with the current syntax, though, right?

 

auto compose = []( auto f, auto g ) { return

    [=]( auto x ) f( g(x) ); };

 

auto curry3 =

   []( auto f ) { return

       [=](auto x) { return [=](auto y) { return [=](auto z) { return

           f(x,y,z); }; }; }; };

 

Though you do have to be a little careful to balance the {‘s and };’s.

 

Herb

 

 

--
 
 
 

Fernando Cacciola

unread,
Dec 20, 2012, 3:12:53 PM12/20/12
to std-pr...@isocpp.org
On Thu, Dec 20, 2012 at 6:07 PM, Nevin Liber <ne...@eviloverlord.com> wrote:
> On 20 December 2012 13:44, Fernando Cacciola <fernando...@gmail.com>
> wrote:
>>
>>
>> > Not putting auto in *already* has a meaning; it is perfectly legal to
>> > write:
>> >
>> > [](string){}
>> >
>> > Changing string to mean "parameter" instead of "type" is a breaking
>> > change
>> > from C++11 and inconsistent with the rest of the language.
>> >
>>
>> OK.
>> Now this is a different argument. You have a point, but, I would say
>> that the solution is simple: disallow unnamed parameters (like they do
>> in the proposal)
>
>
> I don't see how this fixes the problem; it is still a breaking change,
> making it far less likely to pass for C++14. Take the following example:
>
> struct Missiles
> {
> Missiles(int numberToCreate) { /*... */ }
> Missiles& operator()(int numberToLaunch) { /* ... */ }
> };
>
> [](Missiles){ return Missiles(1); }
>
> This behavior has changed silently under the proposal.
>
Hmm, I see.
And right now I don't see how could the conclusion not be that we do
need the placeholder auto to disambiguate (and with it default
argument would be back)


>>
>> >> (FWIW, I would prefer a simpler syntax where you can say (T a) instead
>> >> of <class T>(T a), but that's a lot more difficult given the current
>> >> language definition)
>> >
>> >
>> > Again, I think that is incredibly error prone, because its meaning
>> > changes
>> > based on whether or not T is a lexically available type.
>>
>> Are you referring to the case when you'd use <class T>?
>
>
> No, omitting the <class T> is the error prone case. You need something to
> say what 'T' is.

OK, so the part of the proposal where template syntax is used to name
types is not debated, only the omission of auto.

Klaim - Joël Lamotte

unread,
Dec 20, 2012, 3:35:55 PM12/20/12
to std-pr...@isocpp.org
Would it help having a terse-but-with-auto syntax by keeping the auto based syntax but allowing a ..."shortcut" symbol that would be an alias for auto?
Like @ or $?

Example:

auto f = []( auto a, auto b) a x b;
or
auto f = []( auto a, auto b) { return a x b; }

could be written something like

auto f = []( $ a, $ b) a x b;
or
auto f = []( $ a, $ b) { return a x b; }
or even
auto f = [] $a x $b; // just got the idea while writing this, didn't think about the implications yet...
and allow
auto f = []( $, $ b) { return b; } // first argument is anonymous

OR

auto f = []( @ a, @ b) a x b;
or
auto f = []( @ a, @ b) { return a x b; }
or even
auto f = [] @a x @b; // just got the idea while writing this, didn't think about the implications yet...
and allow
auto f = []( @, @ b) { return b; } // first argument is anonymous

The point being that we just need to know that something is an object of arbitrary type, am I correct?

Auto diagnostic:

 1. it would reserve a new symbol, which makes one less symbol for a new (future) feature
 2. it might require that any possible place where you can use auto, you can use @ (for example), to generalize
 3. ...?

For the example
auto f = [] @a x @b; // maximum tersity

the idea would be to have the expression directly, with just markers to the names which are arguments objects, letting the compiler do the rest.


This is a wild idea coming from reading this discussion so it might be stupid...
What do you think?

Joel Lamotte

Ville Voutilainen

unread,
Dec 20, 2012, 3:51:06 PM12/20/12
to std-pr...@isocpp.org
On 20 December 2012 22:35, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:
> Would it help having a terse-but-with-auto syntax by keeping the auto based
> syntax but allowing a ..."shortcut" symbol that would be an alias for auto?
> Like @ or $?
> This is a wild idea coming from reading this discussion so it might be
> stupid...
> What do you think?

I think I strongly prefer auto to such line noise.

Fernando Cacciola

unread,
Dec 20, 2012, 3:51:46 PM12/20/12
to std-pr...@isocpp.org
>
> For the example
> auto f = [] @a x @b; // maximum tersity
>
Just off the top of my head, I really like that :)

The generalization would be that, in (the body of) a lambda
expression, identifiers of a certain form are implicitly arguments of
the lambda. Each such argument would be of an automatic type as if it
appeared in the parameter list in the form "auto a". If all lamda
parameters are implicit the parameter list can be omitted altogether.

Whether the proper form is @a or has to be something else would be a
separate issue.

I like the direction this is going because I would like lambdas to be
a "second level meta programming tool": they are put in source code to
generate source code, which is itself template code generating the
final concrete source code.

If the above where to be sound and potentially accepted, then one
would think that it might be possible to go further and say that: if
there is a lambda with all implicit lamda arguments, the lambda
introducer [] can also be omitted, which we leads us to:

find_if(range(r), @e == 2 ) ;


Best

Ville Voutilainen

unread,
Dec 20, 2012, 4:01:58 PM12/20/12
to std-pr...@isocpp.org
On 20 December 2012 22:51, Fernando Cacciola
<fernando...@gmail.com> wrote:
>>
>> For the example
>> auto f = [] @a x @b; // maximum tersity
> Just off the top of my head, I really like that :)

Some further points: I would also prefer

1) not adding $ or @ for just lambda uses
2) not adding yet-another-meaning-in-yet-another-language for $ or @

The second point is for those of us unfortunate enough to get
occasional exposure to
shell scripts, perl, and ruby. Replacing auto with @ is utterly
unconvincing to me,
and is just a foolish hack that has negative value. I don't think
maximum tersity
is a valuable goal, I prefer having a short but readable syntax, and
that's at odds
with maximum tersity.

Klaim - Joël Lamotte

unread,
Dec 20, 2012, 4:13:57 PM12/20/12
to std-pr...@isocpp.org
On Thu, Dec 20, 2012 at 10:01 PM, Ville Voutilainen <ville.vo...@gmail.com> wrote:
The second point is for those of us unfortunate enough to get
occasional exposure to
shell scripts, perl, and ruby. Replacing auto with @ is utterly
unconvincing to me,

It was an example, you could use any symbol that doesn't already mean something in the given context (maybe : )
but I suppose any other symbol wouldn't please you anyway?
 
and is just a foolish hack that has negative value. I don't think
maximum tersity
is a valuable goal, I prefer having a short but readable syntax, and
that's at odds
with maximum tersity.

I don't know if maximum tersity have negative value, I was just suggesting that it could solve the two points Herb stated, which assume we go the way of having a terse way to express lambdas.
If a very terse way to express lambdas isn't acceptable, sure it's a hack.

Joel Lamotte


Ville Voutilainen

unread,
Dec 20, 2012, 4:29:20 PM12/20/12
to std-pr...@isocpp.org
On 20 December 2012 23:13, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:
> It was an example, you could use any symbol that doesn't already mean
> something in the given context (maybe : )
> but I suppose any other symbol wouldn't please you anyway?

All ideas I've seen so far look worse than auto to me.

> I don't know if maximum tersity have negative value, I was just suggesting
> that it could solve the two points Herb stated, which assume we go the way
> of having a terse way to express lambdas.

That's a funny assumption because EWG indicated the opposite in Portland,
as far as I recall.

Fernando Cacciola

unread,
Dec 20, 2012, 4:43:12 PM12/20/12
to std-pr...@isocpp.org
On Thu, Dec 20, 2012 at 6:01 PM, Ville Voutilainen
<ville.vo...@gmail.com> wrote:
> On 20 December 2012 22:51, Fernando Cacciola
> <fernando...@gmail.com> wrote:
>>>
>>> For the example
>>> auto f = [] @a x @b; // maximum tersity
>> Just off the top of my head, I really like that :)
>
> Some further points: I would also prefer
>
> 1) not adding $ or @ for just lambda uses
> 2) not adding yet-another-meaning-in-yet-another-language for $ or @
>
> The second point is for those of us unfortunate enough to get
> occasional exposure to
> shell scripts, perl, and ruby.

At the risk of digressing, can you tell us why? I use those languages
every once in a while and from all the complaints I have, their markup
for variable names has never been one.

> Replacing auto with @ is utterly
> unconvincing to me,

Ah, but that's not really what Joel did, even if he presented it as such.

He proposed a syntax in which lambda arguments are implicit. So it not
just (or "not really" to be precise) that auto is replaced by another
symbol: the entire parameter list (where you would put auto) is gone!!
That's a whole new level of tersity, one which IMO pushes lambdas into
the direction I think they should go.

> and is just a foolish hack that has negative value. I don't think
> maximum tersity
> is a valuable goal, I prefer having a short but readable syntax, and
> that's at odds
> with maximum tersity.
>

I agree with the general principle of what you said.

However, I believe lambdas should be the exception.
The reason is that a lambda expression is, IMO, all about tersity. I
don't need a lambda at all. I can write the function object myself.
In fact, to be honest, that's what I do, and because I still don't
find the syntax convenient enough.

Like I said before, IMO a lambda is nothing but a metaprogramming
construct to help me generate a function object easily. The more
simple than writing the function object it is, the more valuable.

In that sense, being able to just write the lambda expression *itself*
and nothing else, as in:

apply(e, @e + 2 );

instead of

apply(e, [](auto e) { return e + 2 ; } ) ;

which is itself instead of:

struct plustwo {
template<class T> T operator() ( T e ) { return e + 2 ; }
} ;

apply(e, plustwo() );


makes the feature really really, really, useful.

stackm...@hotmail.com

unread,
Dec 20, 2012, 5:59:00 PM12/20/12
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com
I like where this is going. Kinda like boost.lambda, just built into the language.

Mikael Kilpeläinen

unread,
Dec 20, 2012, 6:02:44 PM12/20/12
to std-pr...@isocpp.org
> However, I believe lambdas should be the exception.
Considering the apply case below, I think so too.

> apply(e, @e + 2 );
This is very nice, I am just afraid of the consequences of it though.
Also I dislike @ but that is besides the point.



Mikael

Fernando Cacciola

unread,
Dec 20, 2012, 6:38:05 PM12/20/12
to std-pr...@isocpp.org
As I would. So let's discuss that.

Off the top of my head, here's what I think of it (disclaimer: I'm
anything but a compiler writer)

(from my user POV) when the compiler correctly identifies a lambda
expression, it generates the corresponding closure type. Further, when
it sees an application of such lambda, it generates the expression
that creates the closure object, binds the corresponding objects that
are captured, and calls the generated function object with lambda
parameters.

So, the very first consideration would be if the proposed syntax would
allow the compiler to correctly identify the lambda expression.
With the current grammar of [](){} this is clearly possible. I would
imagine that the lambda-introducer (the []) is the token that makes
such identification possible in the current syntax.
I might leave with it if necessary but the whole point of the proposed
simplification is to avoid all unnecessary tokens. Thus, we need a
grammar that also provides a unique token (or token sequence). Off the
top of my head, I would say that @ or $ could function as a token to
identify a lambda expression.

If that is correct, then next step would be if such a grammar, based
on such tokens, would suffice to identify the full lambda expression.
I can't tell so let's just say yes.

Then, would the elements of such a correctly identified lambda be
enough to generate the closure type? here I'm sure it is because we
need:

(1) the captures. If there is lambda-introducer that is as it is now,
and if there is not introducer the simple rule is that there are no
captures.

(2) the parameter-list. If the full lambda expression is correctly
identified, then all implicit arguments are found and generating the
parameter list is trivial:

@a + @b * @c -> ( auto a, auto b, auto c)

(3) the operator() body. This would be the fully-indentified
expression, possibly put inside "{ return (expr) ; }", with implicit
arguments transformed by stripping the special @ token.


I'm sure there would be much more details, but this is to get it started.

Notice that this is compatible and coexistent with actual and
"as-proposed" polymorphic lambdas, since it is really about
automatically generating, or adding into, auto parameters in the
parameter list.

Mikael Kilpeläinen

unread,
Dec 20, 2012, 7:19:25 PM12/20/12
to std-pr...@isocpp.org
> As I would. So let's discuss that.
Lets do.

> (from my user POV) when the compiler correctly identifies a lambda
> expression, it generates the corresponding closure type. Further, when
> it sees an application of such lambda, it generates the expression
> that creates the closure object, binds the corresponding objects that
> are captured, and calls the generated function object with lambda
> parameters.
Indeed, so here that is based on the @, which is part of the
identifier?.. how about clauses
with parenthesis, for example to use comma operator in lambda expressions.
Is (@a + 2) still a lambda expression? Naturally that extends to
arbitrary long expressions.

> If that is correct, then next step would be if such a grammar, based
> on such tokens, would suffice to identify the full lambda expression.
> I can't tell so let's just say yes.
Besides the above issue, I don't see any major problems.

> Then, would the elements of such a correctly identified lambda be
> enough to generate the closure type? here I'm sure it is because we
> need:
I am sure they would be. This, of course, puts some restrictions to this
form of lambdas but
I think that was obvious, and works well to be just "extension" to the
normal syntax.

> I'm sure there would be much more details, but this is to get it started.
Indeed, thank you for that.



Mikael

Fernando Cacciola

unread,
Dec 20, 2012, 7:33:39 PM12/20/12
to std-pr...@isocpp.org
On Thu, Dec 20, 2012 at 9:19 PM, Mikael Kilpeläinen
<mikael.ki...@gmail.com> wrote:
>> As I would. So let's discuss that.
>
> Lets do.
>
>
>> (from my user POV) when the compiler correctly identifies a lambda
>> expression, it generates the corresponding closure type. Further, when
>> it sees an application of such lambda, it generates the expression
>> that creates the closure object, binds the corresponding objects that
>> are captured, and calls the generated function object with lambda
>> parameters.
>
> Indeed, so here that is based on the @, which is part of the identifier?..
> how about clauses
> with parenthesis, for example to use comma operator in lambda expressions.
> Is (@a + 2) still a lambda expression? Naturally that extends to arbitrary
> long expressions.
>
IMO, it must be for this to be truly useful.
Now I'm not an expert in C++ parsing but I would think that it would
be possible to "grow out" the enclosing full expression containing the
implicit lambda parameter. At least to a reasonably useful extent.

>
>> If that is correct, then next step would be if such a grammar, based
>> on such tokens, would suffice to identify the full lambda expression.
>> I can't tell so let's just say yes.
>
> Besides the above issue, I don't see any major problems.
>
>
>> Then, would the elements of such a correctly identified lambda be
>> enough to generate the closure type? here I'm sure it is because we
>> need:
>
> I am sure they would be. This, of course, puts some restrictions to this
> form of lambdas but
> I think that was obvious, and works well to be just "extension" to the
> normal syntax.
>
Right.
The idea is to make it enviously straightforward to create the really
simple polymorphic lambdas, while still possible to write the rest.

Mikael Kilpeläinen

unread,
Dec 20, 2012, 7:58:04 PM12/20/12
to std-pr...@isocpp.org
> IMO, it must be for this to be truly useful.
> Now I'm not an expert in C++ parsing but I would think that it would
> be possible to "grow out" the enclosing full expression containing the
> implicit lambda parameter. At least to a reasonably useful extent.
Certainly, but it makes the parsing more complex. That said, I don't
think it is really a problem (maybe it is for some generated parsers?).


Mikael

John Bytheway

unread,
Dec 20, 2012, 9:04:40 PM12/20/12
to std-pr...@isocpp.org
On 20/12/12 16:43, Fernando Cacciola wrote:
> In that sense, being able to just write the lambda expression *itself*
> and nothing else, as in:
>
> apply(e, @e + 2 );

<snip>

> makes the feature really really, really, useful.

Note that this is very close to what is already offered by libraries
such as Boost.Phoenix. In that case the line would be:

apply(e, _1 + 2 );

(provided you first bring the _1 into scope from the library namespace)

So, there is already a widely-used proof of concept for such a syntax.

John Bytheway

Travis Gockel

unread,
Dec 20, 2012, 10:58:29 PM12/20/12
to std-pr...@isocpp.org
> Certainly, but it makes the parsing more complex.

This is very true...I'm not even sure it is possible to unambiguously determine if a in `[] (a)` is a type or the name of an argument, especially since the behavior of C++11 is in the wild (`a` is always a type...contrast this with D, where `a` is always a value). Even if it is possible, it unquestionably makes the parsing more context-sensitive. The only benefit I see is the ability to drop the N characters of whatever token serves as the placeholder for the type name ("auto", "$", "@" or otherwise). I'm not sure the benefit is worth the cost of the increased grammar complexity.

As far as sigil placeholders go...in my opinion, they contrast the rest of the language. Furthermore, [] ($*&) { } looks funny to me.

Travis Gockel

unread,
Dec 20, 2012, 11:11:46 PM12/20/12
to std-pr...@isocpp.org
Worth mentioning a potential workaround for disambiguating between C++11 and the N3418 proposed single-token lambda function arguments is to have something like `[]<>` be a template-lambda-introducer, which says that its lambda-declarator should treat single-token arguments as values. That syntax might play poorly with the changes to allow the compound-statement in a lambda to be an expression, but I haven't fully thought it through.

Alberto Ganesh Barbati

unread,
Dec 21, 2012, 4:09:18 AM12/21/12
to std-pr...@isocpp.org
I definitely agree. Let me point out that using @ would be disastrous for Objective-C/C++ interoperability and that $ is already being used by some other specific dialect/platform, which I don't recall now. Of course, whether we want to keep compatibility with such uses is debatable, but we have to be aware that the lexical space is more crowded than it seems and every decision comes at a cost.

Ganesh

stackm...@hotmail.com

unread,
Dec 21, 2012, 7:39:38 AM12/21/12
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com
What about §?

Alberto Ganesh Barbati

unread,
Dec 21, 2012, 7:47:36 AM12/21/12
to std-pr...@isocpp.org

Il giorno 21/dic/2012, alle ore 13:39, stackm...@hotmail.com ha scritto:

> What about §?
>

It has to be in the "basic source character set" (see 2.3/2). § is not part of it.

Ganesh

stackm...@hotmail.com

unread,
Dec 21, 2012, 7:50:42 AM12/21/12
to std-pr...@isocpp.org
Neither are @ or $.

Martinho Fernandes

unread,
Dec 21, 2012, 7:58:35 AM12/21/12
to std-pr...@isocpp.org
On Fri, Dec 21, 2012 at 12:38 AM, Fernando Cacciola
<fernando...@gmail.com> wrote:
> On Thu, Dec 20, 2012 at 8:02 PM, Mikael Kilpeläinen
> (2) the parameter-list. If the full lambda expression is correctly
> identified, then all implicit arguments are found and generating the
> parameter list is trivial:
>
> @a + @b * @c -> ( auto a, auto b, auto c)
>

Before we go any further into bikeshedding territory about which weird
looking symbol is better, let us first note the fact that this syntax
does not really cut it in general. What if I want `(auto c, auto b,
auto a)` instead?

Mit freundlichen Grüßen,

Martinho

Daniel Biesiada

unread,
Dec 21, 2012, 8:02:13 AM12/21/12
to std-dis...@isocpp.org, std-pr...@isocpp.org, fai...@gmail.com
Wow,

This is almost same crazy as Javascript's inside function scoping. 
I'm terrified to think how people will use that in practice ;-)

-
Daniel Biesiada


Wiadomość napisana przez Herb Sutter <hsu...@microsoft.com> w dniu 20 gru 2012, o godz. 21:09:

-- 
 
 
 

Fernando Cacciola

unread,
Dec 21, 2012, 8:39:27 AM12/21/12
to std-pr...@isocpp.org
On Fri, Dec 21, 2012 at 9:58 AM, Martinho Fernandes
<martinho....@gmail.com> wrote:

> What if I want `(auto c, auto b, auto a)` instead?
>

OK. I thought I should address that but figured it might not be
necessary. But it is, so:

There is *absolutely no difference in the observed behavior* between

(auto a, auto b, auto c) and (auto a, auto c, auto b)

or any other permutation for that matter.

This is specially true because the order of evaluation to function
arguments is undefined (there is something about parameter order and
default arguments but that is irrelevant here)

The only difference is lexical (what the source code is expressing
about the parameters), and is an important difference but only if you
are indeed expressing a parameter list. In the case in hand we are
specifically not doing that so there is effectively no difference at
all. The corresponding closure type would be defined to have a
parameter list whose parameters are listed in the order they first
appear in the expression, from left to right.

Chris Jefferson

unread,
Dec 21, 2012, 8:45:04 AM12/21/12
to std-pr...@isocpp.org
I think the point was, often function's arguments are not in the same
order as they appear.

For example, I often use lambdas for things like rearranging the
arguments to functions, and filling some values in. Consider for example
wanting to sort largest to smallest, so using [](auto a, auto b) {
return b < a; }.

Now, I could assume in this case that > exists, so I can use @a > @b,
but what if the existing argument was a function f, how I can switch
around the arguments to a function?

Chris

Fernando Cacciola

unread,
Dec 21, 2012, 8:55:05 AM12/21/12
to std-pr...@isocpp.org
On Fri, Dec 21, 2012 at 10:45 AM, Chris Jefferson <ch...@bubblescope.net> wrote:
>
> Now, I could assume in this case that > exists, so I can use @a > @b, but
> what if the existing argument was a function f, how I can switch around the
> arguments to a function?
>
Ah, OK. I did miss it.

It is a good point indeed, though I think it servers to refine the
proposal more than it would serve to discourage it.

It is certainly important to correlate the implicit parameters to the
actual function arguments. The left to right rule I mentioned could it
but for the sake of the ultimate goal, which is the ability to express
simple lambdas as directly as possible, the proven placeholder syntax
would do just fine.

So, we would have implicit lambda arguments which are of a numerical
form, such as @1 + @2 * 3

It's only natural to ask why not just _1, _2 etc directly since they
are in use already? That would be very nice but I don't think is
possible.


--

Klaim - Joël Lamotte

unread,
Dec 21, 2012, 9:14:26 AM12/21/12
to std-pr...@isocpp.org
I think the "overly terse" syntax discussion should happen in another thread as it goes beyond the initial purpose of this one that was feedback about Faisal's implementation.

Joel Lamotte

Nevin Liber

unread,
Dec 20, 2012, 1:20:48 PM12/20/12
to std-pr...@isocpp.org
On 20 December 2012 11:59, Herb Sutter <hsu...@microsoft.com> wrote:

I still think there’s real demand for the terse form that doesn’t require ‘auto’, but there is a design tension here that we’re still working out.


Could you use a different operator to mean auto in this context?  Something like:

[](+a, +b){}

Note:  I'm not necessarily endorsing this kind of thing; I'm just throwing it into the design space.
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

Nevin Liber

unread,
Dec 19, 2012, 9:51:21 PM12/19/12
to std-pr...@isocpp.org
On 19 December 2012 20:41, Fernando Cacciola <fernando...@gmail.com> wrote:

Where it specifically says that auto is NOT allowed (not just not
required), which necessarily disallows unnamed parameters precisely to
avoid the ambiguity.

Wouldn't that be a breaking change from C++11 lambdas?
 
Has this changed?

The paper cited is pre-Portland.  According to n3488:  "Reviewed by EWG in Portland, proceeding with a follow-up paper."

Ville Voutilainen

unread,
Dec 20, 2012, 5:07:17 PM12/20/12
to std-pr...@isocpp.org
On 20 December 2012 23:43, Fernando Cacciola
<fernando...@gmail.com> wrote:
>> Some further points: I would also prefer
>> 1) not adding $ or @ for just lambda uses
>> 2) not adding yet-another-meaning-in-yet-another-language for $ or @
>> The second point is for those of us unfortunate enough to get
>> occasional exposure to
>> shell scripts, perl, and ruby.
> At the risk of digressing, can you tell us why? I use those languages
> every once in a while and from all the complaints I have, their markup
> for variable names has never been one.

I don't hugely mind their markup for variable names. I do mind if c++ suddenly
gains a different markup for variables using $ or @. That's my beef with those,
more meanings to symbols commonly found in other languages.

> However, I believe lambdas should be the exception.
> The reason is that a lambda expression is, IMO, all about tersity. I
> don't need a lambda at all. I can write the function object myself.
> In fact, to be honest, that's what I do, and because I still don't
> find the syntax convenient enough.
> Like I said before, IMO a lambda is nothing but a metaprogramming
> construct to help me generate a function object easily. The more
> simple than writing the function object it is, the more valuable.

I daresay I disagree - maximizing the ease of writing the function at all costs
is not what I'm after, because I have to read the resulting code many more
times than I have to write it. That is why I prefer using auto, and not trying
to make the syntax as terse as possible.

Faisal Vali

unread,
Dec 19, 2012, 11:49:23 PM12/19/12
to std-pr...@isocpp.org
On Wed, Dec 19, 2012 at 8:41 PM, Fernando Cacciola
<fernando...@gmail.com> wrote:
> On Tue, Dec 18, 2012 at 12:50 PM, <tra...@solidfire.com> wrote:
>> The `auto` is required is disambiguate this:
>>
>> [] (a) {}
>>
>> Is `a` an automatically-typed variable or an unnamed argument with the type
>> `a`?
>>
> Really?
>
> Not according to the relevant paper:
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf
>
> Where it specifically says that auto is NOT allowed (not just not
> required), which necessarily disallows unnamed parameters precisely to
> avoid the ambiguity.
>
> Has this changed? I like it better without auto FWIW
>

There was a very strong preference in the Evolution Room of the
Portland Meeting for auto to be mandatory. I believe either option
can be reasonably implemented.

Faisal Vali

unread,
Dec 20, 2012, 6:01:19 PM12/20/12
to Scott Prager, std-pr...@isocpp.org, std-dis...@isocpp.org
On Thu, Dec 20, 2012 at 12:16 PM, Scott Prager
<splinte...@gmail.com> wrote:
>
> I wrote some tests. A few lines caused the compiler to crash so I commented
> them out and labelled them "Crash!".
>
> https://gist.github.com/4347130
>

Ok the latest snapshot contains fixes for all the crashes except for
one which I have been unable to replicate (but am still trying a few
things):
// Crash!
auto singleton2 = []( auto x ) Singleton <typename
std::decay<decltype(x)>::type> ( std::move(x) );

Also, iostreams on linux and mac (in reference to our discussion on
reddit) should now work too.

Once again - thanks for all your feedback and help!

Nevin Liber

unread,
Dec 21, 2012, 7:06:10 PM12/21/12
to std-pr...@isocpp.org
On 19 December 2012 22:49, Faisal Vali <fai...@gmail.com> wrote:

There was a very strong preference in the Evolution Room of the
Portland Meeting for auto to be mandatory.  I believe either option
can be reasonably implemented.

I believe something has to be there (for the reasons I've stated earlier in this thread), but I don't remember discussing if it has to be spelled "auto" and/or another, one-character token could work as well.

And terseness for short expressions is growing on me...

innoc...@gmail.com

unread,
Dec 29, 2012, 10:01:20 AM12/29/12
to std-dis...@isocpp.org, std-pr...@isocpp.org, fai...@gmail.com, dain...@gmail.com, tra...@solidfire.com
so, maybe it'd make sense to introduce some special keyword to disambiguate these cases?


On Tuesday, December 18, 2012 5:50:50 PM UTC+2, tra...@solidfire.com wrote:
The `auto` is required is disambiguate this:

[] (a) {}

Is `a` an automatically-typed variable or an unnamed argument with the type `a`?

On Monday, December 17, 2012 3:38:25 PM UTC-7, dain...@gmail.com wrote:
Cool :)

 Why is "auto" required though? It seems like it would work fine without the keyword..?


nadias...@gmail.com

unread,
Jan 11, 2013, 3:04:08 PM1/11/13
to std-pr...@isocpp.org
I find the current proposal extremely disappointing. If you use lambda's in C#, you can see how elegant they _can_ be. Requiring a type specification for each parameter is cumbersome and ugly. I don't see any reason why each argument to a lambda can't have an implicit template type assigned to it, that can then be inferred by the call context. It doesn't make semantic difference, it is just syntactic sugar. Trying to infer a single token in the parameter list of a lambda as a typename is silly, since it doesn't make any sense to do so.

In addition, I understand that Bjarne wants concepts, and many other people do too. However, I don't think _anything_ should be predicated on concepts ever happening. I for one am not confident they ever will, and I find it frustrating that using lambdas has to be desecrated because concepts "might" happen in our lifetime.

nadias...@gmail.com

unread,
Jan 11, 2013, 3:08:09 PM1/11/13
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com, dain...@gmail.com, tra...@solidfire.com, innoc...@gmail.com


On Saturday, December 29, 2012 10:01:20 AM UTC-5, innoc...@gmail.com wrote:
so, maybe it'd make sense to introduce some special keyword to disambiguate these cases?

On Tuesday, December 18, 2012 5:50:50 PM UTC+2, tra...@solidfire.com wrote:
The `auto` is required is disambiguate this:

[] (a) {}

Is `a` an automatically-typed variable or an unnamed argument with the type `a`?

It's an automatically-typed variable. Having an unnamed argument in a lambda in senseless. You can't overload it, so using it to force the compiler to choose some version of a function isn't possible. You can't refer to it. It is therefore silly to create problem which does not, in practice, exist.

 

Alex Sinyakov

unread,
Jan 11, 2013, 3:12:10 PM1/11/13
to nadias...@gmail.com, std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com, dain...@gmail.com, tra...@solidfire.com
good point! I hope committee will approve [] (a) {} form.
Stop making simple things compicated!
--
Thanks,
Alex

Nevin Liber

unread,
Jan 11, 2013, 3:18:50 PM1/11/13
to std-pr...@isocpp.org
On 11 January 2013 14:08, <nadias...@gmail.com> wrote:


On Tuesday, December 18, 2012 5:50:50 PM UTC+2, tra...@solidfire.com wrote:
The `auto` is required is disambiguate this:

[] (a) {}

Is `a` an automatically-typed variable or an unnamed argument with the type `a`?

It's an automatically-typed variable. Having an unnamed argument in a lambda in senseless. You can't overload it, so using it to force the compiler to choose some version of a function isn't possible. You can't refer to it. It is therefore silly to create problem which does not, in practice, exist.

The reasons for not doing so have already been discussed at length in this thread; it may be worth reviewing the whole discussion.  I'm not seeing any new information here.

Ville Voutilainen

unread,
Jan 11, 2013, 3:19:42 PM1/11/13
to std-pr...@isocpp.org
On 11 January 2013 22:08, <nadias...@gmail.com> wrote:
>>> [] (a) {}
>>> Is `a` an automatically-typed variable or an unnamed argument with the
>>> type `a`?
> It's an automatically-typed variable. Having an unnamed argument in a lambda
> in senseless. You can't overload it, so using it to force the compiler to
> choose some version of a function isn't possible. You can't refer to it. It
> is therefore silly to create problem which does not, in practice, exist.

How is an unnamed argument more senseless in a lambda than in a function,
where I use it for ignoring a parameter without polluting the function body with
a superfluous name?

Travis Gockel

unread,
Jan 11, 2013, 3:23:03 PM1/11/13
to std-pr...@isocpp.org
On Fri, Jan 11, 2013 at 1:08 PM, <nadias...@gmail.com> wrote:


It's an automatically-typed variable. Having an unnamed argument in a lambda in senseless. You can't overload it, so using it to force the compiler to choose some version of a function isn't possible. You can't refer to it. It is therefore silly to create problem which does not, in practice, exist.
 

I agree that's how I would have written the rule if I was starting from scratch -- the issue is that there is already a C++11 standard which unambiguously requires [] (a) {} to be parsed as an unnamed argument. It will be a very tough fight to get the committee to approve a breaking change.

Besides, there are legitimate use cases for unnamed arguments in lambda functions:

void foo(void (*)(Info, Extra));
foo([] (Info x, Extra) { ... });

-- 
Travis Gockel
λ Combinator

Nicol Bolas

unread,
Jan 11, 2013, 3:36:22 PM1/11/13
to std-pr...@isocpp.org

A name is more "pollution" than always having to take up precious space for short functions with a completely pointless type? I mean, it's only pollution when you don't need it, right? Whereas a typename is always pollution when it's just `auto`. So if you're getting "environment friendly", you should be supporting the one that removes the pollution in more cases.

The problem is that this is a breaking change. So we need a solution to that problem. Has anyone considered special lambda declaration syntax that changes the grammar to mean "just an identifier means `auto <identifier>`, not `type`"? Something like this maybe (I am not well-versed enough in C++ grammar to know if this would work. It's just an example):

[]a(var1, var2, var3) {...}

Where `a` is one of those "special identifier" type things that isn't a keyword. Or maybe you can use double parenthesis: (( )). There has to be some grammar that's reasonably short that can take out the pointless word cruft of `auto` from the declaration.

Ville Voutilainen

unread,
Jan 11, 2013, 3:47:21 PM1/11/13
to std-pr...@isocpp.org
On 11 January 2013 22:36, Nicol Bolas <jmck...@gmail.com> wrote:
> A name is more "pollution" than always having to take up precious space for
> short functions with a completely pointless type? I mean, it's only
> pollution when you don't need it, right? Whereas a typename is always
> pollution when it's just `auto`. So if you're getting "environment
> friendly", you should be supporting the one that removes the pollution in
> more cases.

I consider the proposed inconsistencies between lambdas and functions
unfortunate, and
I'm not convinced that the "precious" space is that precious when I'm
reading code.

Zhihao Yuan

unread,
Jan 11, 2013, 4:01:43 PM1/11/13
to std-pr...@isocpp.org
On Fri, Jan 11, 2013 at 2:23 PM, Travis Gockel <tra...@gockelhut.com> wrote:
> Besides, there are legitimate use cases for unnamed arguments in lambda
> functions:
>
> void foo(void (*)(Info, Extra));
> foo([] (Info x, Extra) { ... });

A single name is ambiguous here, however, I noticed that a reference
without a type-specifier is not, like

[] (&a) { ... }

So, how about enforce a special prefix to non-reference parameters? Like:

[] (=a) { ... }

Thus, the two grammars above are two generic lambda parameters.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://4bsd.biz/

Nevin Liber

unread,
Jan 11, 2013, 4:04:04 PM1/11/13
to std-pr...@isocpp.org
On 11 January 2013 14:36, Nicol Bolas <jmck...@gmail.com> wrote:

[]a(var1, var2, var3) {...}

Ultimately, people are going to want to mix concrete types and templated types, as they do with templated functions now.

Part of the charter of EWG is to look at the language "as a whole".  Making the declarations work in a way that is inconsistent with the rest of the language goes against this, IMHO.

Also, the more complicated this proposal gets, the less likely it'll make it into C++14 (whose charter is to "Complete C++11", not invent a whole bunch of new things).  Are polymorphic lambdas a feature you'd rather see sooner than later?

nadias...@gmail.com

unread,
Jan 11, 2013, 4:11:01 PM1/11/13
to std-pr...@isocpp.org

Besides, there are legitimate use cases for unnamed arguments in lambda functions:

void foo(void (*)(Info, Extra));
foo([] (Info x, Extra) { ... });


I don't see that as so compelling a reason as to _require_ a typename. The fact that it might occasionally be convenient to do that is outweighed by the fact that it is nearly always more convenient (and clear) to omit the type names from a lambda parameter list. 

nadias...@gmail.com

unread,
Jan 11, 2013, 4:14:24 PM1/11/13
to std-pr...@isocpp.org

On Friday, January 11, 2013 3:23:03 PM UTC-5, Travis Gockel wrote:
On Fri, Jan 11, 2013 at 1:08 PM, <nadias...@gmail.com> wrote:


It's an automatically-typed variable. Having an unnamed argument in a lambda in senseless. You can't overload it, so using it to force the compiler to choose some version of a function isn't possible. You can't refer to it. It is therefore silly to create problem which does not, in practice, exist.
 

I agree that's how I would have written the rule if I was starting from scratch -- the issue is that there is already a C++11 standard which unambiguously requires [] (a) {} to be parsed as an unnamed argument. It will be a very tough fight to get the committee to approve a breaking change.
 
That may be social reason for the sad "auto" requirement rule, but it is not a satisfying one. Users will gasp in horror, as I did, when they view the mess that has been made of something that can be elegant and readable. As demonstrated by many modern programming languages that support a non-desecrated syntax for lambdas.

nadias...@gmail.com

unread,
Jan 11, 2013, 4:15:59 PM1/11/13
to std-pr...@isocpp.org
This is not a new invention. According to the footnote in the proposal, the auto-less syntax was the intended direction: 

1 Lawrence Crowl: "Yes. The intent was to expand lambda in just this direction after 2012."

Taken from page 2 of N3418=12-0108. 

Richard Smith

unread,
Jan 11, 2013, 4:20:39 PM1/11/13
to std-pr...@isocpp.org
On Fri, Jan 11, 2013 at 12:23 PM, Travis Gockel <tra...@gockelhut.com> wrote:
> On Fri, Jan 11, 2013 at 1:08 PM, <nadias...@gmail.com> wrote:
>>
>>
>>
>> It's an automatically-typed variable. Having an unnamed argument in a
>> lambda in senseless. You can't overload it, so using it to force the
>> compiler to choose some version of a function isn't possible. You can't
>> refer to it. It is therefore silly to create problem which does not, in
>> practice, exist.
>>
>
>
> I agree that's how I would have written the rule if I was starting from
> scratch -- the issue is that there is already a C++11 standard which
> unambiguously requires [] (a) {} to be parsed as an unnamed argument. It
> will be a very tough fight to get the committee to approve a breaking
> change.

I'm not sure that's the case, and it seems worthwhile to put it to the
committee rather than assuming they would oppose it. I would support
such a breaking change, and several other members of the committee
whom I've spoken to were surprised to learn that the parameter name
for a lambda had become optional (in earlier drafts of the lambda
proposal, it was mandatory, in order to allow this extension at a
later date).

Róbert Dávid

unread,
Jan 11, 2013, 4:27:33 PM1/11/13
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com, dain...@gmail.com, tra...@solidfire.com, innoc...@gmail.com, nadias...@gmail.com
I didn't read the previous discussion, so sorry if it came up already.

There is more reasons to have a parameter on a function or lambda, if you happen to write a callback function, you need to match the correct signature. And lambdas in my experience used a lot for callbacks.
Consider the following:
class A{}; class B{}; class C{};
typedef void (*callback1)(A /*required*/, B /*optional*/);
typedef void (*callback2)(A
/*required*/, C /*optional*/);
void func(callback1);
void func(callback2);

void foo() {
    func([](A a, B){ /*Do stuff with only a*/});
}
If B is an automatic-typed variable, this is ambiguous, even though it is perfectly clear what the programmer wanted. Requiring auto if you want a parameter named B makes this a non-issue.

I also like the version with requiring auto better. It makes a lot easier to read the code later, auto practically yelling "hey, there is a new parameter here".

Regards, Robert

Nicol Bolas

unread,
Jan 11, 2013, 4:40:48 PM1/11/13
to std-pr...@isocpp.org


On Friday, January 11, 2013 1:04:04 PM UTC-8, Nevin ":-)" Liber wrote:
On 11 January 2013 14:36, Nicol Bolas <jmck...@gmail.com> wrote:

[]a(var1, var2, var3) {...}

Ultimately, people are going to want to mix concrete types and templated types, as they do with templated functions now.

The different rule would only come into play with arguments that are just an identifier. It says that with identifier-only arguments, the identifier specifies a argument who's type is automatically deduced and who's name is given.

Part of the charter of EWG is to look at the language "as a whole".  Making the declarations work in a way that is inconsistent with the rest of the language goes against this, IMHO.

This will be neither the first nor the last time that changes enter the standard that are "inconsistent with the rest of the language".

Also, the more complicated this proposal gets, the less likely it'll make it into C++14 (whose charter is to "Complete C++11", not invent a whole bunch of new things).  Are polymorphic lambdas a feature you'd rather see sooner than later?

No. I would much rather have to wait until C++17 to get polymorphic lambdas correctly than to have a long-winded, broken version forever in the language, with no possibilities of ever correcting the syntax. I would rather have to write the class by hand than to have horrible syntax like what is being proposed.

However, it would be a strong demonstration of the failure of the standardization process and the committee if we can't get something that so effectively describes what the user wants into C++14.

Nicol Bolas

unread,
Jan 11, 2013, 4:41:52 PM1/11/13
to std-pr...@isocpp.org


On Friday, January 11, 2013 1:01:43 PM UTC-8, Zhihao Yuan wrote:
On Fri, Jan 11, 2013 at 2:23 PM, Travis Gockel <tra...@gockelhut.com> wrote:
> Besides, there are legitimate use cases for unnamed arguments in lambda
> functions:
>
> void foo(void (*)(Info, Extra));
> foo([] (Info x, Extra) { ... });

A single name is ambiguous here, however, I noticed that a reference
without a type-specifier is not, like

    [] (&a) { ... }

So, how about enforce a special prefix to non-reference parameters? Like:

    [] (=a) { ... }

Thus, the two grammars above are two generic lambda parameters.

That works for me. I don't know if the grammar is doable in terms of C++ conflicts and such, but it looks similar to how [] syntax works, so it has consistency working for it.

Nevin Liber

unread,
Jan 11, 2013, 5:13:40 PM1/11/13
to std-pr...@isocpp.org
On 11 January 2013 15:20, Richard Smith <ric...@metafoo.co.uk> wrote:

> I agree that's how I would have written the rule if I was starting from
> scratch -- the issue is that there is already a C++11 standard which
> unambiguously requires [] (a) {} to be parsed as an unnamed argument. It
> will be a very tough fight to get the committee to approve a breaking
> change.

I'm not sure that's the case, and it seems worthwhile to put it to the
committee rather than assuming they would oppose it.

A.  It was already brought to the committee in Portland, and the auto-less syntax was discouraged by EWG.
B.  Some of the people opposing it in this discussion are on that committee.

Nevin Liber

unread,
Jan 11, 2013, 5:24:53 PM1/11/13
to std-pr...@isocpp.org
On 11 January 2013 15:40, Nicol Bolas <jmck...@gmail.com> wrote:

Part of the charter of EWG is to look at the language "as a whole".  Making the declarations work in a way that is inconsistent with the rest of the language goes against this, IMHO.

This will be neither the first nor the last time that changes enter the standard that are "inconsistent with the rest of the language".

That doesn't mean we should do it gratuitously.  Consistency is hard, because you cannot be consistent with everything; that doesn't mean you shouldn't be consistent with anything.
 

Also, the more complicated this proposal gets, the less likely it'll make it into C++14 (whose charter is to "Complete C++11", not invent a whole bunch of new things).  Are polymorphic lambdas a feature you'd rather see sooner than later?

No. I would much rather have to wait until C++17 to get polymorphic lambdas correctly than to have a long-winded, broken version forever in the language, with no possibilities of ever correcting the syntax.


That isn't the choice; if we put it off, who knows what form it will take?  Do you want it in C++14, or are you willing chance waiting until some point in the future?  5+ years is a long time to wait for a feature people want now.

Assuming you can convince the committee to reverse its Portland guidance, one option would be to write and present in Bristol a proposal to deprecate optional parameter names in lambdas, as that at least paves the way.

IMO, a better (as in a little more likely to succeed) proposal is to come up with a general terse syntax that is a replacement for

template<typename T>
U foo(T t);

Nevin Liber

unread,
Jan 11, 2013, 5:38:41 PM1/11/13
to std-pr...@isocpp.org
On 11 January 2013 15:14, <nadias...@gmail.com> wrote:

On Friday, January 11, 2013 3:23:03 PM UTC-5, Travis Gockel wrote:

I agree that's how I would have written the rule if I was starting from scratch -- the issue is that there is already a C++11 standard which unambiguously requires [] (a) {} to be parsed as an unnamed argument. It will be a very tough fight to get the committee to approve a breaking change.
 
That may be social reason for the sad "auto" requirement rule, but it is not a satisfying one.

Breakage has a cost and slows adoption.  While some breakage is inevitable, the bar is high for C++.  Other languages have different constraints.
 
Users will gasp in horror,

Some users will "gasp in horror" no matter what we do.

andy....@gmail.com

unread,
Jan 11, 2013, 9:12:16 PM1/11/13
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com
I have a quick question concerning the standardization of generic lambdas. I am not sure if this is the place where to ask, so I apologize in advance if that is not the case.

The current standard forbids declaring local types which contain template member functions. Clearly, generic lambdas will have to be an exception to this rule.
My question is: will this restriction be lifted completely, or will generic lambdas be the only exception allowed?

Thank you for your consideration,

Andy

Faisal Vali

unread,
Jan 11, 2013, 11:11:48 PM1/11/13
to andy....@gmail.com, std-pr...@isocpp.org, std-dis...@isocpp.org
It is my personal opinion that if the restriction on local class
templates or local member templates is to be lifted, a separate
proposal would be required (and I really hope someone writes one). As
far as I know, the EWG has not had any official discussion so far
about lifting this restriction (or enabling this feature); but, a
formal and well thought out proposal could make all the difference...

Nikolay Ivchenkov

unread,
Jan 12, 2013, 3:20:55 AM1/12/13
to std-pr...@isocpp.org
On Friday, December 21, 2012 12:35:55 AM UTC+4, Klaim - Joël Lamotte wrote:

For the example
auto f = [] @a x @b; // maximum tersity

the idea would be to have the expression directly, with just markers to the names which are arguments objects, letting the compiler do the rest.


This is a wild idea coming from reading this discussion so it might be stupid...
What do you think?

Personally, I would prefer to use a short notation like this:

    [][%1 + %2]

rather than

    [](auto &&_1, auto &&_2) { return FORWARD(_1) + FORWARD(_2); }

where FORWARD is defined as

    #define FORWARD(x) static_cast<decltype(x) &&>(x)

The general form with explicit declarations of parameters could still be used when the desirable semantics cannot be expressed via the reduced form.

Daniel Krügler

unread,
Jan 12, 2013, 6:26:41 AM1/12/13
to std-dis...@isocpp.org, std-pr...@isocpp.org, fai...@gmail.com
2013/1/12 <andy....@gmail.com>:
Both issues exists, but there is a tendency to make these decisions
separate and uncoupled. This makes it easier to have a larger design
space. The overlap of both is well-known to the committee but it was
evaluated that lambda expressions *can* be made polymorphic with still
not allowing for general member templates within local types. This
doesn't mean that the constrain will not be lifted, but it will be
deferred to a different decision.

- Daniel

Andrea Proli

unread,
Jan 12, 2013, 6:35:26 AM1/12/13
to fai...@gmail.com, std-pr...@isocpp.org, std-dis...@isocpp.org
Thank you for your answer.

I was used to think of lambdas as syntactic sugar, but *generic* lambdas are not: the generated closure breaks the rule from paragraph 14/2:

"A template-declaration can appear only as a namespace scope or class scope declaration".

I am unaware of the reasons why this restriction exists in the first place (I did some research but with no success), so I cannot write a proposal on lifting it. However, if good reasons exist, I am curious whether the fact that generic lambdas break it will create troubles.

Kind regards,

Andy 

Daniel Krügler

unread,
Jan 12, 2013, 6:52:51 AM1/12/13
to std-dis...@isocpp.org, fai...@gmail.com, std-pr...@isocpp.org
2013/1/12 Andrea Proli <andy....@gmail.com>:
> I was used to think of lambdas as syntactic sugar, but *generic* lambdas are
> not: the generated closure breaks the rule from paragraph 14/2:
>
> "A template-declaration can appear only as a namespace scope or class scope
> declaration".
>
> I am unaware of the reasons why this restriction exists in the first place
> (I did some research but with no success), so I cannot write a proposal on
> lifting it. However, if good reasons exist, I am curious whether the fact
> that generic lambdas break it will create troubles.

Polymorphic (or generic, if you prefer) lambda expressions don't
provide the full capacities of templates. As you say, they just are
syntactic sugar for some sub-space of possible template constructions.
It is therefore much simpler to add them compared to starting with a
support for local templates from begin with. This would not
necessarily result in a conflict with 14/2, you just add one
exceptional rule and that's it.

- Daniel

Andrea Proli

unread,
Jan 12, 2013, 7:05:15 AM1/12/13
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com
Well, if an exceptional rule is to be added, then it means it does conflict with 14/2 :) but I see what you mean.


- Daniel

--




Daniel Krügler

unread,
Jan 12, 2013, 7:33:09 AM1/12/13
to std-dis...@isocpp.org, std-pr...@isocpp.org, fai...@gmail.com
2013/1/12 Andrea Proli <andy....@gmail.com>:
> Well, if an exceptional rule is to be added, then it means it does conflict
> with 14/2 :) but I see what you mean.

Well, I described it as "exceptional" rule, but there doesn't need to
exist such normative sentence. It all depends on the actual wording
for polymorphic lambdas whether such a sentence is needed. If the
language specifies polymorphic lambda expressions and if it is clear
that this includes local scope, there is no extra wording needed. You
could add a non-normative note to the general exclusion rule, just as
another example.

- Daniel

Andrea Proli

unread,
Jan 12, 2013, 7:42:39 AM1/12/13
to std-pr...@isocpp.org, std-dis...@isocpp.org, fai...@gmail.com
I agree it all depends on how they are going to formalize this. I just wanted to point out that the current interpretation of lambdas as syntactic sugar for generating a locally defined closure won't generalize to polymorphic lambdas, because that would make them syntactic sugar for defining something which is not allowed otherwise. Which means, that they would not be syntactic sugar.

Andy



- Daniel

--




wolfei...@gmail.com

unread,
Jan 25, 2013, 8:55:12 AM1/25/13
to std-dis...@isocpp.org, std-pr...@isocpp.org, fai...@gmail.com, dain...@gmail.com, iba...@gmail.com
I disagree. I think it should be resolved the other way, because that's way more likely to be what's useful. Unused arguments still have the old C-style void(param) kind of thing. The problem of "Whoops, I can't use unnamed parameters" is a lot less than "Whoops, every other thing in my program is the "auto" keyword."


On Wednesday, December 19, 2012 9:45:36 PM UTC, iba...@gmail.com wrote:

[] (a) {}

Is `a` an automatically-typed variable or an unnamed argument with the type `a`?

Isn't this another case of - if it can be a typename it is a typename? 
Reply all
Reply to author
Forward
0 new messages