That's slightly sloppy phrasing. It captures it, but it does not duplicate it, so it's lifetime is tied to the stack frame of the function you declared it in.
That's the definition of a closure. I'm not sure if "lambda" is necessarily synonymous with "closure" or just synonymous with "anonymous function", but lambdas are closures in many languages.
They should try to make something syntactically compatible with C++ lambdas. It's annoying that the two languages are more and more incompatible for cosmetic reasons.
You're not passing a compound statement expression as a function pointer. You are passing the result of the evaluation of that expression --which is a function pointer -- as a function pointer.
It's been officially supported in GCC since about a decade ago, I believe. It's not part of the C language, so if you're writing this code, it's no longer C. It also requires executable stacks.
Because of the way nested functions are implemented in GCC.
If you call a nested function it has to know the frame address of the containing function in order to refer to its local variables. So if you take the address of such a function the program actually receives the address of a "trampoline": a small sequence of instructions which first loads the frame address and then calls the real function.
The trampoline itself is generated dynamically and putting it on the stack turns out to be cheaper than heap allocating it.
> and putting it on the stack turns out to be cheaper than heap allocating it.
Well, more so that C has no concept of the heap. That's entirely contained within the C libraries. So, the language implementation itself can't do heap allocations (at least, not without sacrificing any chance of using it in embedded or kernel dev situations where you don't have heap allocation, or where you need to use custom allocators)
The article indicates its not officially supported, although it could be.
Ian Lance Taylor replied that the behavior is
undefined, but so far stable. His suggestion was
to open a bug and request that this desirable (!!!)
behavior be explicitly permitted.
Right. And of course the whole idea is prone to insane amounts of fail.
> Thus, if you access the enclosing environment, you
> must ensure that the lifetime of this lambda is bound by the
> lifetime of the enclosing environment (i.e., until the enclosing
> function returns). This means that if you access local
> variables, bad things will happen. If you don't access local
> variables, you're fine.
Might as well avoid the complications, hoist the function and pass a function pointer with some context (assuming it's needed).
printf("I am bad and evil %p\n", ({int bad_and_evil(void){return 0;};&bad_and_evil;}));
printf("I am bad and evil2 %d\n", ({0x4FFFFFF;}));
void* result = ({void* bad_and_evil(int dummy){return 0;};&bad_and_evil;});
printf("bad and evil 3 = %p\n", result);
* shudder * Getting a return value from a block, by inserting it in parantheses.
Anonymous functions are very handy, and I think they should really be taken a step further. There's really no reason why it shouldn't be possible to pass an actual function body where a function pointer is required:
int v[...];
qsort( v, ..., (a, b) { return *(int*)a - *(int*)b } );
Such usage would also have an added benefit of letting the compiler do the type inference for a, b and the return value and not needing to explicitly specify them in qsort() call.
Local functions would be a nice compromise between the unreadable glop that was posted and the need to declare an entirely separate function to execute localized actions.
I personally think so, as I think blocks in C are a clumsy way around the issue (probably because C doesn't natively have garbage collection) and it feels natural in go, but I know others will disagree.
Also, I don't think you can make it anonymous, can you?
39 comments
[ 2.3 ms ] story [ 92.1 ms ] threadIn short, you can only do downwards funargs.
So this probably isn't really a lambda.
I think of "lambda" as a language construct that creates closures. "anonymous functions" are of course just a simpler subset of closures.
Much better solution to the problem, hopefully coming to standard GCC soon(tm).
http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC62
I do not find it obvious from that documentation that you can pass a compound statement expression as a function pointer.
And touche', I just glanced at the contents of the macro before replying.
Having that series of operations produce something useful is unexpected, to say the least.
It's nothing I'd want to see in code that I maintain, but I think you have to give it a bit more credit. Besides that, it's cute :)
If you call a nested function it has to know the frame address of the containing function in order to refer to its local variables. So if you take the address of such a function the program actually receives the address of a "trampoline": a small sequence of instructions which first loads the frame address and then calls the real function.
The trampoline itself is generated dynamically and putting it on the stack turns out to be cheaper than heap allocating it.
Well, more so that C has no concept of the heap. That's entirely contained within the C libraries. So, the language implementation itself can't do heap allocations (at least, not without sacrificing any chance of using it in embedded or kernel dev situations where you don't have heap allocation, or where you need to use custom allocators)
"Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of CommonLisp"
(bar the environment/scope issue it avoids that is)
Also, I don't think you can make it anonymous, can you?
Sorry, I just like the irony.
1) If I define a lambda inside a function, I cannot return the lambda from the function and use it right?
2) Recursive lambdas are not possible on account of the lack of recursion in C macros (not sure if that even makes sense without 1).