在C语言中模拟Lambda表达式?

7
我需要提醒一下,我是在生成C代码,而不是手动操作。我这么说是因为它的背后可能有很多代码,但是编译器应该可以管理所有这些。那么,在C语言中如何模拟lambda表达式呢?我想我可以在源代码中的某个地方生成一个带有随机名称的函数,然后调用它?但我不太确定。我还没有尝试过任何东西,因为我想先将这个想法记录下来,然后再实现它。
是否有一些预处理指令或宏可以使这个过程更加简洁?Jon Blow的编程语言Jai启发了我尝试编写编译器,他似乎在他的语言中实现了Lambda表达式。然而,我认为他做了一些生成字节码的事情,然后转换成C语言?我不确定。
编辑: 我正在开发一个编译器,这只是我的一个项目,让我保持忙碌,同时我也想学习更多关于编译器的知识。我主要使用clang,在Ubuntu 14.10上工作。我没有任何垃圾收集机制,但我想尝试一些类似智能指针/ Rust / ARC等灵感的内存模型来进行垃圾回收,即几乎没有开销。我选择C语言是因为我想更深入地研究它。我的项目是自由软件,只是一个业余项目。

你是在什么情况下生成C代码?使用哪个操作系统和编译器?为什么不使用更好的语言(如Common Lisp或Ocaml)?你是否正在实现某个编译器?你有垃圾回收器吗?请编辑你的问题以改进它。 - Basile Starynkevitch
什么是该项目,它的 URL 是什么? - Basile Starynkevitch
很遗憾,你的编程语言没有垃圾回收或闭包。 - Basile Starynkevitch
是的,我的意思是这是一种可能性。我只是在玩一些想法,你有没有什么关于将代码生成到另一种源语言的书籍可以推荐的? - metro-man
我强烈推荐Queinnec的《Lisp In Small Pieces》(学习一些Scheme也是值得的,也许只是为了理解这本书)。 - Basile Starynkevitch
我会阅读的,谢谢! - metro-man
1个回答

9
有几种方法可以实现在C语言中使用lambda表达式。重要的是要理解lambda表达式提供了闭包,并且闭包将“代码”与“数据”(封闭的值)混合在一起;注意对象也将“代码”与“数据”混合在一起,对象和闭包之间存在相似性。另请参见closuresthis answer关于Programmers的回答。

传统上,在C语言中,不仅使用函数指针,而且采用约定来处理callbacks。例如,这就是GTK的情况:每次传递函数指针时,还会传递一些数据。您可以将回调(使用带有一些void*数据的C函数指针的约定)视为实现闭包的一种方式。

由于你生成C代码(这是一个明智的想法,我在MELT中也在做类似的事情,在Linux上生成C ++代码,在运行时将其编译成共享对象,并使用dlopen-s),因此你可以采用回调约定并向生成的每个函数传递一些闭合值。

你还可以考虑将闭合值作为static变量,但这种方法通常不明智。

过去有一些生成闭包的机器特定跳板代码的lambda.h头文件库(基本上是生成将一些关闭值作为参数推送然后调用某个例程的代码)。您可以使用一些JIT编译技术(使用libjit,GNU lightningLLVMasmjit等)来完成相同的操作。另请参见libffi以调用仅在运行时已知签名的任意函数。

请注意,闭包和垃圾回收之间存在着强烈但间接的关系(欲了解更多,请阅读GC手册),并且每个函数式语言都有垃圾回收机制也不是偶然的。C++11的lambda函数是一个例外(很难理解C++11闭包的所有内存管理复杂性)。因此,如果您正在生成C代码,则可以并且可能应该使用Boehm保守的垃圾收集器(其封装了dlopen),这样您就可以对闭包进行垃圾回收。 (您可以使用其他GC库,例如Ravenbrook的MPS或我未维护的Qish...)然后,您可以约定每个生成的C函数将其闭包作为第一个参数。
我建议阅读斯科特的《编程语言实践》,并且(假设您知道一点Scheme或Lisp; 如果您不知道,则应该学习一些Scheme并阅读SICP昆尼克的《小型Lisp》(如果您恰好会阅读法语,请阅读最新的变体)。

@user3839220:不过,请编辑您的问题以改进它。我非常好奇您在做什么,为什么要问,以及您如何生成C代码?您的项目是自由软件吗? - Basile Starynkevitch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接