Lambdas in C
walfield.org
walfield.org
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 :)
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.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)
> 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).Deleted comment
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.
Much better solution to the problem, hopefully coming to standard GCC soon(tm).
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.
In short, you can only do downwards funargs.
qsort (array, sizeof (array) / sizeof (array[0]), sizeof (array[0]),
lambda (int, (const void *a, const void *b),
{
dump ();
printf ("Comparison %d: %d and %d\n",
++ comparison, *(const int *) a, *(const int *) b);
return *(const int *) a - *(const int *) b;
}));Sorry, I just like the irony.
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.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).
"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)
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. package main
import "fmt"
func main() {
add := func(x int, y int) int{
return x+y
}
max := func(x int, y int) int{
if x>y {return x}
return y
}
fmt.Printf("lambda: add:%d\n",add(2,3))
fmt.Printf("lambda: max:%d\n",max(2,3))
}
Although it'd be nice if you could have a ternary or something like return {x} if x>y else {y} #include <stdio.h>
int main (int argc, char const *argv[]) {
int (^add)(int, int) = ^(int x, int y) {
return x + y;
};
int (^max)(int, int) = ^(int x, int y) {
return (x > y) ? x : y;
};
printf("block: add:%d\n", add(2,3));
printf("block: max:%d\n", max(2,3));
return 0;
}Also, I don't think you can make it anonymous, can you?
func(x int, y int){fmt.Printf("%d\n",x+y)}(2,4) ^(int x, int y){printf("%d\n",x+y);}(2,4);
Automatic memory management is interesting, but orthogonal. val := func(x int, y int) int{return x+y}(2,4)