An implementation of Generic lambdas (Request for feedback)

297 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

Matt D.

unread,
Dec 18, 2012, 9:22:22 AM12/18/12
to std-dis...@isocpp.org
On 12/17/2012 20:05, Faisal Vali wrote:
> 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.

Hi!

I have a semi-OT question regarding the above-mentioned binaries -- is
VS2010 required?
I've tried using them w/ VS2012, but it seems to have trouble parsing
the headers:

> generic-lambda-clang-12-17-12.exe -std=c++1y -c hello.cpp -emit-llvm
-o hello.bc
In file included from hello.cpp:1:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\iostream:6:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\istream:6:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\ostream:6:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\ios:6:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\xlocnum:10:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\streambuf:6:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\xiosbase:6:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\xlocale:8:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\stdexcept:7:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\xstring:6:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\xmemory0:9:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\xutility:8:
In file included from C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\utility:8:
C:\Program Files (x86)\Microsoft Visual Studio
11.0\VC\include\type_traits:1072:33: error: '_Ty' does not refer to a value
_HAS_TRIVIAL_MOVE_CONSTRUCTOR(_Ty)
. . .
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.

Best,

Matt

Faisal Vali

unread,
Dec 18, 2012, 9:54:18 AM12/18/12
to std-dis...@isocpp.org
On Tue, Dec 18, 2012 at 8:22 AM, Matt D. <mat...@gmail.com> wrote:
> On 12/17/2012 20:05, Faisal Vali wrote:
>>
>> 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.
>
>
> Hi!
>
> I have a semi-OT question regarding the above-mentioned binaries -- is
> VS2010 required?
> I've tried using them w/ VS2012, but it seems to have trouble parsing the
> headers:
>

I have not tested it with VS2012.
But even with VS2010, I haven't figured out how to get the iostream
library or the standard library to work (admittedly I have not spend
too much time trying to figure it out either since I don't use clang
on windows to do any active development) - But if anyone knows how to
do that, I would certainly like to know too.

What I do currently for outputting is include <cstdio> and use printf
(i believe you have to use option -c when compiling with clang). I am
certainly no authority in this space - I feel I know just enough to
compile fragments of code and test them.

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`?

Matt D.

unread,
Dec 18, 2012, 11:11:27 AM12/18/12
to std-dis...@isocpp.org
I see -- at least it wasn't me doing something wrong, then ;-)
Outputting with printf works, thanks!

Best,

Matt

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

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

 

 

--
 
 
 

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:

-- 
 
 
 

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? 

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.

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!

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 §?

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?

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

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

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...

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."
Reply all
Reply to author
Forward
0 new messages