Google 網路論壇不再支援新的 Usenet 貼文或訂閱項目,但過往內容仍可供查看。

Lambda's in GCC

瀏覽次數:1,090 次
跳到第一則未讀訊息

Joe D

未讀,
2010年8月5日 上午11:05:522010/8/5
收件者:
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

未讀,
2010年8月5日 上午11:06:582010/8/5
收件者:
And if anybody is interested I can post an implementation of a foreach
loop, that works with ICC, GCC and Clang.

Gene

未讀,
2010年8月5日 下午1:28:052010/8/5
收件者:

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

Ben Bacarisse

未讀,
2010年8月5日 下午1:29:412010/8/5
收件者:
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

未讀,
2010年8月5日 下午2:21:042010/8/5
收件者:

"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

未讀,
2010年8月5日 下午3:21:542010/8/5
收件者:
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

未讀,
2010年8月5日 下午4:53:292010/8/5
收件者:
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

未讀,
2010年8月5日 下午5:03:382010/8/5
收件者:
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

未讀,
2010年8月5日 下午6:01:292010/8/5
收件者:

I see what you mean, thanks.

- Joe

Uno

未讀,
2010年8月5日 晚上8:22:462010/8/5
收件者:

> 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

未讀,
2010年8月5日 晚上11:20:112010/8/5
收件者:
"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

未讀,
2010年8月5日 晚上11:26:242010/8/5
收件者:
"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

未讀,
2010年8月6日 下午2:05:082010/8/6
收件者:

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

未讀,
2010年8月10日 凌晨3:36:512010/8/10
收件者:


Ben,

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

Block expression in particular.

--
Uno

0 則新訊息