Não é mais possível fazer postagens ou usar assinaturas novas da Usenet nos Grupos do Google. O conteúdo histórico continua disponível.
Dismiss

Lambda's in GCC

1.089 visualizações
Pular para a primeira mensagem não lida

Joe D

não lida,
5 de ago. de 2010, 11:05:5205/08/2010
para
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

não lida,
5 de ago. de 2010, 11:06:5805/08/2010
para
And if anybody is interested I can post an implementation of a foreach
loop, that works with ICC, GCC and Clang.

Gene

não lida,
5 de ago. de 2010, 13:28:0505/08/2010
para

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

Ben Bacarisse

não lida,
5 de ago. de 2010, 13:29:4105/08/2010
para
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

não lida,
5 de ago. de 2010, 14:21:0405/08/2010
para

"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

não lida,
5 de ago. de 2010, 15:21:5405/08/2010
para
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

não lida,
5 de ago. de 2010, 16:53:2905/08/2010
para
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

não lida,
5 de ago. de 2010, 17:03:3805/08/2010
para
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

não lida,
5 de ago. de 2010, 18:01:2905/08/2010
para

I see what you mean, thanks.

- Joe

Uno

não lida,
5 de ago. de 2010, 20:22:4605/08/2010
para

> 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

não lida,
5 de ago. de 2010, 23:20:1105/08/2010
para
"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

não lida,
5 de ago. de 2010, 23:26:2405/08/2010
para
"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

não lida,
6 de ago. de 2010, 14:05:0806/08/2010
para

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

não lida,
10 de ago. de 2010, 03:36:5110/08/2010
para


Ben,

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

Block expression in particular.

--
Uno

0 nova mensagem