Today, I learned that gcc C has supported lambda functions since at least version 3.0.4. I wish I had known sooner.

At the recent GNU Hackers Meeting in the Hague, Paolo Carlini gave a talk about C++0x and gcc. One of the new features he mentioned is C++'s support for lambda functions. If g++ has them, I thought, it shouldn't be too hard to introduce them into gcc. I asked Paulo and he said that he had heard of a project that was working on exactly this. Cool.

Today, I went searching for the people working on lambda functions in gcc. I didn't find them. Instead, I found something even cooler: GNU C's compound statement and a macro are enough to get 95% of lambdas. Consider:

#include <stdlib.h>
#include <stdio.h>


/* Create a lambda function.  Note: unlike lambdas in functional
   languages, this lambda does not capture the containing
   environment.  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.  */
#define lambda(l_ret_type, l_arguments, l_body)         \
  ({                                                    \
    l_ret_type l_anonymous_functions_name l_arguments   \
      l_body                                            \
    &l_anonymous_functions_name;                        \
  })

int
main (int argc, char *argv[])
{
  int array[] = { 4, 3, 1, 2, 5 };

  void dump (void)
  {
    int i;
    for (i = 0; i < sizeof (array) / sizeof (array[0]); i ++)
      printf ("%d ", array[i]);
    printf ("\n");
  }

  printf ("Initial: ");
  dump ();

  /* Ensure that the lambda is a nested function and thus requires a
     trampoline.  */
  int comparison = 0;

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

  printf ("Sorted: ");
  dump ();

  return 0;
}

Output:

$ gcc -Wall a.c -o a && ./a
Initial: 4 3 1 2 5 
4 3 1 2 5 
Comparison 1: 4 and 3
3 4 1 2 5 
Comparison 2: 2 and 5
3 4 1 2 5 
Comparison 3: 1 and 2
3 4 1 2 5 
Comparison 4: 3 and 1
3 4 1 2 5 
Comparison 5: 3 and 2
3 4 1 2 5 
Comparison 6: 3 and 5
3 4 1 2 5 
Comparison 7: 4 and 5
Sorted: 1 2 3 4 5 

That's awesome. And, it only uses features that have been supported by gcc for over a decade. FTW.

The question that remained was: is this behavior reliable or is it based on an implementation quirk? I emailed the gcc-help list. 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.