用于生成编程的非C ++语言?

时间:2008-09-22 18:34:54

标签: haskell lisp clojure metaprogramming boo

C ++可能是static metaprogrammingJava doesn't support it最受欢迎的语言。

除C ++之外是否还有其他支持生成编程的语言(创建程序的程序)?

15 个答案:

答案 0 :(得分:32)

模板样式元编程的替代方法是在各种Lisp实现中看到的宏样式。我建议下载Paul Graham's On Lisp,如果你对使用在JVM上运行的宏的Lisp感兴趣,也可以查看Clojure

Lisp中的宏比C / C ++风格强大得多,并且本身构成了一种语言 - 它们用于元编程。

答案 1 :(得分:24)

让我列出少数重要细节,了解元编程如何在lisp 中运作(或scheme或{{3} },或选择你最喜欢的“动态”语言:

  • 在lisp中进行元编程时,你不必处理两种语言。元级代码使用与其生成的对象级代码相同的语言编写。元编程不仅限于两个层面,而且在大脑上也更容易。
  • 在lisp中,您可以在运行时使用编译器。事实上,编译时/运行时区别在那里感觉非常人为,并且非常依赖于您放置观点的位置。在lisp中只需要一个函数调用就可以将函数编译为机器指令,然后可以将它们用作第一类对象;即它们可以是未命名的函数,可以保存在局部变量或全局哈希表等中......
  • lisp中的
  • 非常简单:一堆函数填充在哈希表中并提供给编译器。对于编译器即将编译的每个表单,它会查询该哈希表。如果它找到一个函数,然后在编译时用原始表单调用它,并代替原始表单,它将编译此函数返回的表单。 (模数一些非重要的细节)所以lisp宏基本上是编译器的插件
  • 在lisp中编写一个评估lisp代码的lisp函数大约是两页代码(通常称为 eval )。在这样的功能中,您有能力在元级别上引入您想要的任何新规则。 (让它快速运行需要付出一些努力......就像引导一种新语言一样......)。

使用lisp元编程实现可以作为用户库的随机示例(这些是常见lisp库的实际示例):

  • 使用分隔的延续扩展语言(hu.dwim.delico)
  • 实现一个可以在javascript中使用的 js-to-lisp-rpc 宏(从lisp生成)。它扩展为js / lisp代码的混合,自动发布(在http请求中)所有引用的局部变量,在服务器端解码它们,在服务器上运行lisp代码体,并将返回值返回给javascript侧。
  • 添加prolog,如回溯到与“普通”lisp代码无缝集成的语言(请参阅screamer)
  • slate到常见的lisp(包含 reader宏的示例,它们是lisp解析器的插件)
  • 大量的小型DSL,如XML templating extensionloop,方便循环播放

答案 2 :(得分:13)

模板元编程实质上是滥用模板机制。我的意思是你基本上得到了你所期望的功能,这是一个无计划的副作用 - 它是一团糟,并且(尽管工具越来越好)是一个真正的痛苦,因为语言没有支持你这样做(我应该注意到,我对这方面的最新技术经验已经过时了,因为我基本上放弃了这种方法。虽然我没有听说过任何重大进展) / p>

在98年左右解决这个问题是驱使我寻找更好解决方案的原因。我可以编写依赖它的有用系统,但它们是地狱般的。四处寻找最终使我成为Common Lisp。当然,模板机制是Turing完成,但是同样是intercal。

Common Lisp做元编程“正确”。你可以使用该语言的全部功能,没有特殊的语法,并且因为语言非常动态,你可以用它做更多的事情。

当然还有其他选择。没有其他语言我使用的元编程比Lisp更好,这就是我将它用于研究代码的原因。你可能想要尝试别的东西有很多原因,但这些都是权衡取舍。您可以查看Haskell / ML / OCaml等。许多函数式语言都具有接近Lisp宏的强大功能。你可以找到一些.NET目标的东西,但它们都非常边缘(在用户群等方面)。在工业上使用的语言中,没有一个大玩家真的有这样的东西。

答案 3 :(得分:11)

NemerleBoo是我个人最喜欢的事情。尽管文档很差,但Nemerle的宏语法非常优雅。 Boo的文档非常好,但它的宏不太优雅。然而,两者都工作得非常好。

两者都是.NET,因此如果您使用IKVM,它们可以轻松地与C#和其他.NET语言(甚至Java二进制文件)进行互操作。

编辑:澄清一下,我的意思是Lisp意义上的宏,而不是C的预处理器宏。这些允许在编译时定义新语法和繁重的元编程。例如,Nemerle提供的宏将在编译时针对您的SQL服务器验证您的SQL查询。

答案 4 :(得分:9)

Nim是一种相对较新的编程语言,它对静态元编程提供了广泛的支持,并生成了高效的(类似C ++)编译代码。

http://nim-lang.org/

它支持编译时功能评估,通过宏进行类似lisp的AST代码转换,编译时反射,可以使用任意值进行参数化的泛型类型,以及可用于创建用户定义的高级的术语重写类型感知的窥视孔优化。甚至可以在编译过程中执行可能影响代码生成的外部程序。例如,考虑与本地运行的数据库服务器通信,以验证代码中的ORM定义(通过某些DSL提供)是否与数据库的模式匹配。

答案 5 :(得分:6)

"D" programming language与C ++类似,但有更好的元编程支持。以下是仅使用编译时元编程编写的光线跟踪器示例:

Ctrace

此外,还有一个名为“Concept GCC”的gcc分支,它支持C ++没有的元编程结构(至少还没有)。

Concept GCC

答案 6 :(得分:5)

Common Lisp支持以多种不同方式编写程序的程序。

1)程序数据和程序“抽象语法树”是统一的(S表达式!)

2)defmacro

3)阅读器宏。

4)MOP

其中,真正令人兴奋的是MOP。阅读“元对象协议的艺术”。我保证,这会改变你的想法!

答案 7 :(得分:4)

我建议Haskell。这是一个描述其编译时元编程功能的paper

答案 8 :(得分:3)

Haskell的大量工作:领域特定语言(DSL),可执行规范,程序转换,部分应用程序,分阶段计算。很少有链接可以帮助您入门:

答案 9 :(得分:2)

'元编程'对于这个特定的功能来说真的是一个坏名字,至少当你讨论多种语言时,因为只有一小段语言需要这个功能:

  • 静态
  • 编译为机器语言
  • 在编译时针对性能进行了大量优化
  • 可扩展用户定义的数据类型(C ++中的OOP)
  • 非常受欢迎

取出其中任何一个,并且'静态元编程',只是没有意义。因此,如果任何远程主流语言具有类似的东西,我会感到惊讶,正如C ++所理解的那样。

当然,动态语言和几种函数式语言支持完全不同的概念,也称为元编程。

答案 10 :(得分:2)

ML系列语言专门为此目的而设计。 OCaml最着名的成功案例之一是用于高性能FFT的FFTW库,它是几乎完全由OCaml程序生成的C代码。

干杯, Jon Harrop。

答案 11 :(得分:2)

大多数人都试图找到一种具有“终极反思”的语言 用于自我检查和“eval”之类的东西,用于实现新代码。 这些语言很难找到(LISP是一个主要的反例) 他们当然不是主流。

但另一种方法是使用一组可以检查的工具, 生成和操作程序代码。累积奖金是一种工具 专注于Java。 http://jackpot.netbeans.org/

我们的DMS软件再造工具包是 这样一个工具,适用于C,C ++,C#,Java,COBOL,PHP, Javascript,Ada,Verilog,VHDL和其他各种语言。 (它使用生产质量前端使其能够读取 所有这些语言)。 更好的是,它可以在同一时刻使用多种语言。 见http://www.semdesigns.com/Products/DMS/DMSToolkit.html

DMS之所以成功,是因为它提供了一个常规方法和支持基础设施,可以完全访问作为AST的程序结构,并且在大多数情况下还有额外的数据,如符号表,类型信息,控制和数据流分析,这些都是完成复杂程序所必需的操纵。

答案 12 :(得分:1)

Lisp支持一种“元编程”形式,虽然与C ++模板元编程不同。此外,你的术语“静态”在这种情况下可能意味着不同的东西,但Lisp也支持静态类型,如果这就是你的意思。

答案 13 :(得分:1)

元语言(ML),当然:http://cs.anu.edu.au/student/comp8033/ml.html

答案 14 :(得分:1)

使用哪种语言都没有关系-它们中的任何一个都可以执行异构生成元编程。 采用任何动态语言(例如Python,Clojure或Haskell)(如果您是打字迷),并使用该宿主语言编写可以自己编译的模型成为您想要或被团队/雇主强迫使用的主流语言。

我发现对象图是用于内部模型表示的良好模型。此图可以在单个节点中混合属性和有序子图,这是属性语法和AST固有的。因此,对象图解释可以是您的宿主语言和目标语言之间的有效层,并且可以充当在数据结构上定义的某种非语法语言。

最接近的模型是AST:以Python(宿主语言)为目标,以C ++语法(目标语言)描述AST树:

# from metaL import *
class Object:
    def __init__(self, V):
        self.val = V
        self.slot = {}
        self.nest = []


class Module(Object):
    def cc(self):
        c = '// \ %s\n' % self.head(test=True)
        for i in self.nest:
            c += i.cc()
        c += '// / %s\n' % self.head(test=True)
        return c

hello = Module('hello')

# <module:hello> #a04475a2

class Include(Object):
    def cc(self):
        return '#include <%s.h>\n' % self.val

stdlib = Include('stdlib')
hello // stdlib

# <module:hello> #b6efb657
#     0: <include:stdlib> #f1af3e21

class Fn(Object):
    def cc(self):
        return '\nvoid %s() {\n}\n\n' % self.val

main = Fn('main')
hello // main

print(hello.cc())
// \ <module:hello>
#include <stdlib.h>

void main() {
}

// / <module:hello>

但是,您不受构造的对象图的抽象级别的限制:您不仅可以自由添加自己的类型,而且对象图可以解释自身,因此可以像Lisp中的列表一样修改自身。