

Anonymous functions in C - C--
https://github.com/graphitemaster/lambdapp

======
mtdewcmu
This is basically a way of obfuscating your C code. If you want to write
obfuscated code, C++ has extensive support for this. I think it's actually a
strength of C to not have many features. It ultimately makes code more
readable and reliable.

~~~
raverbashing
I don't think I can agree more with your comment.

C++ in fact is only usable (in a team) if its features are pruned and limited
in a team. Really

Throw in some fine preprocessor magic and you'll end up with completely
unmaintanable and impossible to understand code.

~~~
mtdewcmu
Yeah. C is a boring language that barely ever changes. But I'm not sure there
isn't wisdom in being dull.

~~~
nitrogen
Compound literals in C are awesome like it's 1999:

Assuming you have this:

    
    
       struct point {
          float x, y, z;
       };
       void do_something_with_point(struct point *p);
    

You can do this:

    
    
       do_something_with_point(&(struct point){.x = 1.5, .y = 1.5, .z = 3.5});

~~~
mtdewcmu
You can take the address of a literal?

Being able to specify a literal for a struct is useful. You can, for instance,
put the literal in a macro and use the macro to initialize or reset a struct.
It's better than having to write additional functions to do something trivial.

~~~
nitrogen
Yes, you can. You can use it to create an approximation of named parameters,
because struct members that don't have an initializer will default to zero.
It's still not nearly as compact as, say, Ruby, but for C it's pretty awesome
and fast.

~~~
mtdewcmu
That's interesting. You know you can pass structs by value, too, so I'm not
sure how necessary it is to take the address.

~~~
nitrogen
It can be useful for an API that expects pointers for whatever reason.

------
overgard
That's neat, but without closures I don't really see how you could do much
with it outside of toy examples. Going off the examples -- how often do you
write something like a foreach or a map or reduce that doesn't reference its
enclosing scope?

~~~
billsix
As long as the stack frame is still active, the local variables are still
alive and valid. So you could pass a local function as a parameter, but you
could not return it. I think jwz called these "downward funargs".

GCC supports it [http://gcc.gnu.org/onlinedocs/gcc/Nested-
Functions.html](http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html)

~~~
mtdewcmu
GCC's nested functions are implemented with trampolines, so there will be a
performance penalty. For the amount that you gain, they seem like a bad idea.
Tying your code to GCC for the sake of a small amount of convenience is a bad
idea.

~~~
billsix
The question to which I responded did not inquire about performance nor about
portability

[http://tirania.org/blog/archive/2011/Feb-17.html](http://tirania.org/blog/archive/2011/Feb-17.html)

~~~
mtdewcmu
My comment was about GCC's local functions. It wasn't really about your
comment, so I regret if you took it personally.

~~~
billsix
Thank you. Much respect, sorry if I was harsh.

------
yason
Anonymous (or inner) functions aren't really valuable per se but syntactic
sugar for writing the code into a static function somewhere in the same file:
closures give anonymous (or inner) functions the power which is what makes
them useful.

------
misframer
If you use clang, blocks are another approach.

[0]
[http://en.wikipedia.org/wiki/Blocks_(C_language_extension)](http://en.wikipedia.org/wiki/Blocks_\(C_language_extension\))

[1]
[http://clang.llvm.org/docs/BlockLanguageSpec.html](http://clang.llvm.org/docs/BlockLanguageSpec.html)

~~~
graphitemaster
The problem with clang blocks is they're represented as a Objective-C object,
this makes them unusable in APIs that expect a function pointer, the only way
you can cast them to a function pointer is to define the structure which
represents the block and mmap executable code pages to marshal the call. Such
a library exists that binds them to libffi here
[https://github.com/mikeash/MABlockClosure](https://github.com/mikeash/MABlockClosure)
This feat alone makes blocks essentially useless unless your entire API is
also block-based, as in T (^foo)(...) vs T(*foo)(...).

~~~
mtdewcmu
I don't think they could be an ObjectiveC object, because they're described as
C, not ObjectiveC.

I think the problems you're describing are ones that are going to be faced in
any attempt at C closures. Closures have memory attached, that's the appeal of
them and also the source of all the problems.

~~~
graphitemaster
Nope, they're an ObjectiveC object with some specialties at the compiler
level. Google how they're implemented.

~~~
fyolnish
An objective-c object is just a pointer to a struct. You don't need the
objective-c runtime to call a block.

Block_copy etc are implemented in libclosure which iirc does not require
libobjc either. But of course if you ARE writing objc, they are valid objects
and can be treated as such

~~~
graphitemaster
Correct, the problem is to call the function you cannot treat it as a standard
function since it's pointing to a struct, the struct does contain the actual
function pointer but there is an implicit `this' first argument to that
function pointer which has to be that struct itself. This means you cannot use
the block in an API that explicitly requires a function pointer, instead the
API must specifically be aware of the block and would need to support it.

~~~
fyolnish
Of course, there's no way around that except to write block variants for those
functions. stdlib on osx for example has block variants of most functions that
take function pointers (`man qsort_b` for an example)

But if you write your program to use blocks from the start, that's not a big
problem.

------
malkia
Wondering how a debugger would react to this code?

~~~
graphitemaster
Lambdapp inserts #line directives into the source code, compilers are required
to respect those directives and utilize them when producing debug sections in
the binary. For instance in the case of gcc/clang on *nix the compiler will
produce .debug_line sections as part of the DWARF debug format. Debuggers like
gdb and even valgrind utilize this information to provide correct output. So
to answer your question, a debugger would react to this code exactly how it
should react, as if the lambda was called via a function and the file / line
should be correct.

~~~
malkia
I'm more asking as in debugger integration with versioning system (p4, git,
etc.) - Say you've got a crashdump, and was able to track it down to some
specific source code release - now you should've also saved the intermediate
generated files somewhere - but this means that these might have to go back in
p4/git/svn/etc. or find alternative place for them... Generating them again
won't be the same.

Similar problem is with say Qt's generated moc_Xxx source, Ui_xxx source, etc.
files - unless you make the effort of storing these generated files somewhere
you might have problems debugger later.

This is in general my "arrgh" against code generation, and "aargh" is not
against it - it's simply when you had forgot to keep the files somewhere and
the crashdump snaps fingers at you...

