
Lambdas in C - wingo
http://walfield.org/blog/2010/08/25/lambdas-in-c.html
======
eps
In other words - he discovered gcc's ({ }) construct and decided to write a
macros named _lambda_ around it.

<http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC62>

~~~
wingo
To me it's a bit more surprising: it's a statement expression, containing a
nested function, then we take the address of that nested function.

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 :)

~~~
tjr
Any idea if this is now officially supported in GCC? The blog post is from
nearly a year ago.

~~~
ori_b
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.

~~~
xerampelin
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.

~~~
ori_b
Oh. Right, because of the new scope that the anonymous block creates. My
mistake.

------
jensnockert
Blocks, <http://clang.llvm.org/docs/BlockLanguageSpec.txt>

Much better solution to the problem, hopefully coming to standard GCC
soon(tm).

~~~
Rexxar
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.

------
brohee
Am I really out of my mind or is this not a lambda at all but just an
anonymous function?

~~~
StrawberryFrog
If an anonymous function can capture state from the enclosing code block, and
outlive that code block, then it's a lambda.

So this probably isn't really a lambda.

~~~
philwelch
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.

~~~
StrawberryFrog
You're right, my terms are sloppy. Are there rigorous definitions, or does it
vary between languages?.

I think of "lambda" as a language construct that creates closures. "anonymous
functions" are of course just a simpler subset of closures.

------
Kototama
_Note: unlike lambdas in functional languages, this lambda does not capture
the containing environment._

~~~
ori_b
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.

In short, you can only do downwards funargs.

------
athom
My favorite part: _l_anonymous_functions_name_

Sorry, I just like the irony.

------
snorkel
Cute, but functions pointers suit me just fine.

~~~
huhtenberg
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.

------
wbhart
I have not been able to work out two things here:

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).

------
chrisjsmith
Isn't this a step closer to Greenspuns Tenth Rule?

"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)

------
jpr
More accurate title would be "Something like, but not as useful or generic as,
lambdas in gcc's dialect of C".

~~~
madmoose
One might say, to paraphrase Douglas Adams, that it's almost, but not quite,
entirely unlike lambdas.

------
CPlatypus
If I worked on static code analysis tools for a living, this would make me
cry.

------
demallien

      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.

------
juiceandjuice
This is just too clumsy, and this is exactly why I think go will take off.

    
    
      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}

~~~
gok
Is that really that much better than C blocks?

    
    
        #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;
        }

~~~
juiceandjuice
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?

    
    
      func(x int, y int){fmt.Printf("%d\n",x+y)}(2,4)

~~~
gok
You sure can.

    
    
       ^(int x, int y){printf("%d\n",x+y);}(2,4);
    

Automatic memory management is interesting, but orthogonal.

