在 C 中模拟 lambdas?

Emulating lambdas in C?

我应该提一下,我是用 C 语言生成代码,而不是手动执行此操作。我这样说是因为如果它背后有很多代码并没有太大关系,因为编译器应该管理所有这些。无论如何,我将如何在 C 中模拟 lambda?我在想我可以在源代码的某处生成一个具有随机名称的函数然后调用它吗?我不太确定。我还没有真正尝试过任何东西,因为我想在实施之前先把想法记下来。

有没有我可以做的某种预处理器指令,或者有什么宏可以让这件事变得更干净?我受到 Jon Blow 的启发尝试编译器开发,他似乎用他的语言 Jai 实现了 Lambdas。但是,我认为他在生成字节码的地方做了一些事情,然后进入 C?我不确定。

编辑: 我正在研究编译器,编译器只是我的一个项目,让我很忙,而且我想了解更多关于编译器的知识。我主要使用 clang,我在 Ubuntu 14.10。我没有任何垃圾收集,但我想尝试使用某种智能 pointer-y/rust/ARC 启发的垃圾收集内存模型,即几乎没有开销。我选择了C,因为我想更多地涉猎它。我的项目是免费软件,只是一个爱好项目。

有几种方法可以做到("having" C 中的 lambda)。要理解的重要一点是 lambda 给出 closures and that closures are mixing "code" with "data" (the closed values); notice that objects are also mixing "code" with "data" and there is a similarity between objects and closures. See also this answer on Programmers.

传统上,在 C 中,您不仅使用函数指针,而且还采用了关于 callbacks. This for instance is the case with GTK约定:每次传递函数指针时,您也传递一些数据。您可以将回调(约定 为 C 函数指针提供一些 void* 数据)作为实现闭包的一种方式。

既然你生成了 C 代码(这是一个明智的想法,我在 MELT 中做了类似的事情,它在 Linux- 在运行时生成 C++ 代码,将它编译成一个共享对象, dlopen-s that) 你可以采用回调约定并将一些封闭值传递给你生成的每个函数。

您也可以将闭合值视为 static 变量,但这种方法通常是不明智的。

过去有一些 lambda.h 头库生成特定于机器的 trampoline code for closures (essentially generating a code which pushes some closed values as arguments then call some routine). You might use some JIT compilation techniques (using libjit, GNU lightning, LLVM, asmjit, ....) to do the same. See also libffi 来调用 arbitrary 函数(签名已知于仅运行时)。

请注意,闭包和 garbage collection (read the GC handbook for more), and it is not by accident that every functional language has a GC. C++11 lambda functions are an exception on this (and it is difficult to understand all the intricacies of memory management of C++11 closures). So if you are generating C code, you could and probably should use Boehm's conservative garbage collector (which is wrapping dlopen) and you would have closure GC-ed values. (You could use some other GC libraries, e.g. Ravenbrook's MPS or my unmaintained Qish...之间存在很强但间接的关系...) 那么您可以约定每个生成的 C 函数都将其闭包作为第一个参数。

我建议阅读 Scott's book on Programming Language Pragmatics and (assuming you know a tiny bit of Scheme or Lisp; if you don't you should learn a bit of Scheme and read SICP) Queinnec's book Lisp In Small Pieces (if you happen to read French, read the latest French variant)。