Skip to content

Latest commit

 

History

History
154 lines (107 loc) · 4.44 KB

c-lambda.org

File metadata and controls

154 lines (107 loc) · 4.44 KB

Let It Be Lambda (λ)

Book recommendation: Let Over Lambda—50 Years of Lisp by Doug Hoyte

Peculiarities of Org-Mode C Code Blocks

My starting point is Derek Feichtinger’s discussion and the official C, C++, D Source Code Blocks in Org Mode. Considering how much boilerplate there is to C code, Org Babel does a decent job in bringing some literacy to the picture. We get noweb syntax, can pass variables by header arguments, and can CALL source blocks as functions. However, an unpleasant side-effect of those parameters is the creation of global variables in the tangled C code, which makes me uncomfortable. (OCD?)

In C, nothing prevents us from reducing some boilerplate through a strict block-local variables discipline. From the perspective of structuring a larger piece of C code that’s not sufficient though, because it casts a shadow of obscurity over code blocks due to potential references to variables outside the block scope. Looking at a noweb reference such as <<block>>, I can’t really tell which variables from the current lexical scope it references. Conversely, when implementing the code behind <<block>>, I don’t remember anymore what is in referents’ scope. Ideally, there would be a way to pass arguments, and there is, but the price, currently, are global variables. They say that we can’t have λ-functions in C, but what’s holding us back?

Lambda Helper

For this collection, we’ve wrapped standard headers and macros into a single header file called literate-hdf5.h.

These are the standard header files included.

#include "hdf5.h"

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

The more interesting bit is the lambda macro by Al Williams.

#define lambda(lambda$_ret, lambda$_args, lambda$_body) \
  ({                                                    \
    lambda$_ret lambda$__anon$ lambda$_args             \
      lambda$_body                                      \
      &lambda$__anon$;                                  \
  })

It uses two features of GNU C (--std=gnu99), namely, nested functions and statement expressions, which lets us wrap C code blocks as “lambda functions”, thereby making longer pieces of code easier to follow and digest.

lambda(<return type>, ([type1 arg1, type2 arg2, ...]), { <lambda body>  })

Such a lambda can then be invoked like a C-function pointer:

#include "literate-hdf5.h"

int main()
{
  unsigned majnum, minnum, relnum;
  H5get_libversion(&majnum, &minnum, &relnum);

  printf
    ("%f\n",
     (*lambda(float, (float x), { return x*x; })) (majnum+minnum+relnum)
     );

  return 0;
}
196.0

I can live with that, because now I can break this up into:

#include "literate-hdf5.h"

int main()
{
  unsigned majnum, minnum, relnum;
  H5get_libversion(&majnum, &minnum, &relnum);

  printf
    ("%f\n",
     (*
      <<lambda-square>>) (majnum+minnum+relnum)
     );

  return 0;
}
196.0

and

lambda (float, (float x),
        {
          return x*x;
        })

No global variables and no obscure references!