Lambda's in GCC

962 views
Skip to first unread message

Joe D

unread,
Aug 5, 2010, 11:05:52 AM8/5/10
to
I'm posting this in case someone finds it useful, I've already posted
it a couple of times in answers to stack overflow. It's an macro to
create lambda expressions in GCC, however it only works in GCC no
other compilers support it (not even clang).

#define lambda(return_type, body_and_args) \
({ \
return_type __fn__ body_and_args \
__fn__; \
})

Use it like this:

int (*max)(int, int) = lambda (int , (int x, int y) { return x > y ?
x : y; });

Or with qsort:

qsort (array, 42, sizeof (int), lambda (int, (const void * a, const
void * b)
{
return *(int*)a - *(int*)b;
}));

As I've said, I'm just posting it in case anybody find's it useful.

Joe D

unread,
Aug 5, 2010, 11:06:58 AM8/5/10
to
And if anybody is interested I can post an implementation of a foreach
loop, that works with ICC, GCC and Clang.

Gene

unread,
Aug 5, 2010, 1:28:05 PM8/5/10
to

It's a bit grand to call this lambda, since you can't bind lexically
enclosing variables. Nice trick though.

Ben Bacarisse

unread,
Aug 5, 2010, 1:29:41 PM8/5/10
to
Joe D <joe.da...@gmail.com> writes:

> I'm posting this in case someone finds it useful, I've already posted
> it a couple of times in answers to stack overflow. It's an macro to
> create lambda expressions in GCC, however it only works in GCC no
> other compilers support it (not even clang).
>
> #define lambda(return_type, body_and_args) \
> ({ \
> return_type __fn__ body_and_args \
> __fn__; \
> })
>
> Use it like this:
>
> int (*max)(int, int) = lambda (int , (int x, int y) { return x > y ?
> x : y; });

I don't think that is enough like a normal lambda to call it a lambda.
As I understand the GCC extension you are using, it can't capture
bindings that are in scope when the lambda returns its pointer.

<snip>
--
Ben.

BGB / cr88192

unread,
Aug 5, 2010, 2:21:04 PM8/5/10
to

"Ben Bacarisse" <ben.u...@bsb.me.uk> wrote in message
news:0.cf4cc6f31c8512b1ca12.2010...@bsb.me.uk...

yeah...

I once considered something similar (although possibly with variable
capture) as a compiler extension with a syntax like:
<type>(<args>) { <body> }

so, for example:
int(int x, int y) { x+y; }
would behave similarly to a lambda.

or, a keyword like "__fun" could reduce the addition of parser complexity
(or possible ambiguity).


however, I never really implemented this feature (I started later becomming
a bit more conservative with compiler extensions, mostly since I tend to
share a lot of code between my compiler and native compilers such as GCC or
MSVC, and more "extreme" compiler extensions essentially get in the way of
code-mobility).

the result then is that most of my extensions either:
exist in existing compilers;
serve some "necessary" role (can't be reasonably done by other means, rare);
offer a performance advantage and can be trivially emulated (such as my
vector extensions, which can use built in vectors in my compiler, and fall
back to generic SIMD types or structs for other compilers, and are generally
wrapped in macros or inline functions which themselves use the
compiler-specific mechanisms).

since a lambda does none of the above, I haven't added it.

or such...


Joe D

unread,
Aug 5, 2010, 3:21:54 PM8/5/10
to
On Aug 5, 6:29 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:

What exactly do you mean? If you mean you can't use local variables
from the enclosing scope then your wrong, try it out.

Rob Kendrick

unread,
Aug 5, 2010, 4:53:29 PM8/5/10
to
On Thu, 5 Aug 2010 12:21:54 -0700 (PDT)
Joe D <joe.da...@gmail.com> wrote:

> > I don't think that is enough like a normal lambda to call it a
> > lambda. As I understand the GCC extension you are using, it can't
> > capture bindings that are in scope when the lambda returns its
> > pointer.
> >
>

> What exactly do you mean? If you mean you can't use local variables
> from the enclosing scope then your wrong, try it out.

Can you continue to use those automatic variables from the enclosing
scope if the enclosing scope returns a function pointer to your
"lambda" to its caller, who then calls it?

B.

Ben Bacarisse

unread,
Aug 5, 2010, 5:03:38 PM8/5/10
to
Joe D <joe.da...@gmail.com> writes:

> On Aug 5, 6:29 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> Joe D <joe.davis...@gmail.com> writes:
>> > I'm posting this in case someone finds it useful, I've already posted
>> > it a couple of times in answers to stack overflow. It's an macro to
>> > create lambda expressions in GCC, however it only works in GCC no
>> > other compilers support it (not even clang).
>>
>> > #define lambda(return_type, body_and_args) \
>> >   ({ \
>> >     return_type __fn__ body_and_args \
>> >     __fn__; \
>> >   })
>>
>> > Use it like this:
>>
>> > int (*max)(int, int) = lambda (int , (int x, int y) { return x > y ?
>> > x : y; });
>>
>> I don't think that is enough like a normal lambda to call it a lambda.
>> As I understand the GCC extension you are using, it can't capture
>> bindings that are in scope when the lambda returns its pointer.
>>
>> <snip>
>

> What exactly do you mean? If you mean you can't use local variables
> from the enclosing scope then your wrong, try it out.

Yes, that's the general idea, but it goes slightly further than using
local variables from the enclosing scopes. With a true lambda form, the
enclosing scopes may have "finished" but the lambda still carries the
binding during its lifetime. For example:

#include <stdio.h>



#define lambda(return_type, body_and_args) \
({ \
return_type __fn__ body_and_args \
__fn__; \
})

int (*adder(int what))(int)
{
return lambda(int, (int x) { return x + what; });
}

int main(void)
{
int (*inc1)(int) = adder(1);
int (*inc2)(int) = adder(2);
printf("%d %d\n", inc1(1), inc2(1));
return 0;
}

This prints 3 and 3 rather than 2 and 3. If I duplicate the printf call
(which messes up that stack some more) I get a seg fault.

--
Ben.

Joe D

unread,
Aug 5, 2010, 6:01:29 PM8/5/10
to

I see what you mean, thanks.

- Joe

Uno

unread,
Aug 5, 2010, 8:22:46 PM8/5/10
to

> I see what you mean, thanks.

$ gcc -std=c99 -Wall -Wextra lambda1.c -o out
$ ./out
3 3
$ cat lambda1.c
#include <stdio.h>

#define lambda(return_type, body_and_args) \
({ \
return_type __fn__ body_and_args \
__fn__; \
})

int (*adder(int what))(int)
{
return lambda(int, (int x) { return x + what; });
}

int main(void)
{
int (*inc1)(int) = adder(1);
int (*inc2)(int) = adder(2);
printf("%d %d\n", inc1(1), inc2(1));
return 0;
}

// gcc -std=c99 -Wall -Wextra lambda1.c -o out
$

Interesting. Been a while since I looked at this stuff.

Ben's in clc seem to be sharper than the rest of us.
--
Uno

Mark

unread,
Aug 5, 2010, 11:20:11 PM8/5/10
to
"Joe D" <joe.da...@gmail.com> wrote in message
news:3b86e8fe-566c-4e8b...@f6g2000yqa.googlegroups.com...

> I'm posting this in case someone finds it useful, I've already posted
> it a couple of times in answers to stack overflow. It's an macro to
> create lambda expressions in GCC, however it only works in GCC no
> other compilers support it (not even clang).
>
> #define lambda(return_type, body_and_args) \
> ({ \
> return_type __fn__ body_and_args \
> __fn__; \
> })

What gcc extension is being used? I failed to find anything relevant in my
"info gcc" for 4.1.1.

--
Mark

Ben Bacarisse

unread,
Aug 5, 2010, 11:26:24 PM8/5/10
to
"Mark" <mark_cruz...@hotmail.com> writes:

Two things:

(A) A block expression[1]. When gcc has extensions turned on, ({...}) is
an expression whose value can use the full syntax of a block to
calculate the result (__fn__ in the macro).

(B) Nested function definitions[2]. The line

return_type __fn__ body_and_args

will expand to a function definition nested inside the block in the
block expression.

[1] http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Statement-Exprs.html#Statement-Exprs

[2] http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Nested-Functions.html#Nested-Functions
--
Ben.

William Ahern

unread,
Aug 6, 2010, 2:05:08 PM8/6/10
to

http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html

clang supports statement expressions, but not nested functions.

I'm not convinced that declaring and defining a nested function inside of a
statement expression is valid because

[a]ny temporaries created within a statement within a statement
expression will be destroyed at the statement's end.

Uno

unread,
Aug 10, 2010, 3:36:51 AM8/10/10
to


Ben,

I'm gonna read these links and have questions for you.

Block expression in particular.

--
Uno

Reply all
Reply to author
Forward
0 new messages