24

C++ 可能是最流行的静态元编程语言,而Java 不支持它

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

4

15 回答 15

33

模板样式元编程的替代方案是您在各种 Lisp 实现中看到的宏样式。如果您对带有在 JVM 上运行的宏的 Lisp 感兴趣,我建议您下载Paul Graham 的On Lisp并查看Clojure 。

Lisp 中的宏比 C/C++ 风格强大得多,并且本身就构成了一种语言——它们是为元编程设计的。

于 2008-09-22T18:36:56.487 回答
25

让我列出一些有关元编程如何在 lisp(或schemeslate或选择您最喜欢的“动态”语言)中工作的重要细节:

  • 在 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边。
  • 将类似回溯的序言添加到与“正常”lisp 代码非常无缝集成的语言中(参见尖叫者)
  • 普通 lisp的XML 模板扩展(包括作为lisp 解析器插件的阅读器宏示例)
  • 大量的小型 DSL,例如循环迭代,以便于循环
于 2008-09-23T10:45:41.990 回答
14

模板元编程本质上是对模板机制的滥用。我的意思是,你基本上可以从一个计划外的副作用中得到你所期望的——这是一团糟,而且(尽管工具越来越好)一个真正的痛苦,因为语言没有支持你做这件事(我应该注意,我在这方面的最新经验已经过时了,因为我基本上放弃了这种方法。不过,我还没有听说有任何重大进展)

在大约 98 年左右解决这个问题是促使我寻找更好的解决方案的原因。我可以编写依赖它的有用系统,但它们是地狱般的。闲逛最终让我找到了 Common Lisp。当然,模板机制是图灵完备的,但是 intercal 也是如此。

Common Lisp 可以“正确”地进行元编程。当你做这件事时,你拥有语言的全部力量,没有特殊的语法,而且因为语言是非常动态的,你可以用它做更多的事情。

当然还有其他选择。我用过的任何其他语言都没有比 Lisp 更好的元编程,这就是我将它用于研究代码的原因。虽然有很多原因你可能想尝试其他东西,但这一切都将是权衡。你可以看看 Haskell/ML/OCaml 等。许多函数式语言都有一些接近 Lisp 宏的功能。您可以找到一些针对 .NET 的东西,但它们都非常边缘化(就用户群等而言)。工业使用语言的大玩家都没有这样的东西,真的。

于 2008-09-22T19:49:04.627 回答
12

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

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

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

于 2008-09-22T18:37:08.917 回答
10

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

http://nim-lang.org/

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

于 2015-07-28T14:01:48.817 回答
6

D”编程语言类似于 C++,但具有更好的元编程支持。这是一个仅使用编译时元编程编写的光线追踪器示例:

跟踪

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

海合会概念

于 2008-09-22T19:22:40.867 回答
5

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

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

2)defmacro

3) 阅读器宏。

4) 澳门币

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

于 2008-09-23T17:51:53.557 回答
4

我推荐Haskell。这是一篇描述其编译时元编程功能的论文。

于 2008-09-22T18:38:04.487 回答
3

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

于 2008-11-19T08:01:28.773 回答
2

'元编程'对于这个特定的特性来说确实是一个坏名字,至少在你讨论一种以上的语言时,因为这个特性只需要一小部分语言:

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

取出其中任何一个,以及“静态元编程”,都是没有意义的。因此,如果任何远程主流语言都有类似的东西,就像在 C++ 上所理解的那样,我会感到惊讶。

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

于 2008-09-22T19:29:56.420 回答
2

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

干杯,乔恩·哈罗普。

于 2008-10-19T10:03:50.737 回答
2

大多数人试图找到一种具有“终极反射”的语言来进行自我检查,并找到一种类似“eval”的语言来具体化新代码。这样的语言很难找到(LISP 是一个主要的反例),它们当然不是主流。

但另一种方法是使用一组可以检查、生成和操作程序代码的工具。Jackpot 就是这样一个专注于 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 的程序结构,并且在大多数情况下,附加数据,如符号表、类型信息、控制和数据流分析,都是执行复杂程序操作所必需的。

于 2009-06-14T04:48:17.497 回答
1

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

于 2008-09-22T18:36:43.833 回答
1

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

于 2008-09-22T19:33:44.493 回答
0

你使用什么语言并不重要——它们中的任何一个都能够进行异构生成元编程。使用任何动态语言,例如 Python 或 Clojure,或者如果您是类型爱好者,则使用 Haskell,并用这种宿主语言编写模型,这些模型能够将它们自己编译成您想要或被您的团队/雇主强制使用的一些主流语言。

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

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

# 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 中的列表一样修改自己。

于 2020-08-16T09:31:23.113 回答