通用编程与元编程

时间:2010-10-14 21:07:03

标签: programming-languages metaprogramming generic-programming

究竟有什么区别?似乎这些术语可以互换使用,但是阅读了Objective-c的维基百科条目,我遇到了:

  

除了C的程序风格   编程,C ++直接支持   某些形式的面向对象   编程,通用编程和   元编程。

参考C ++。显然他们有所不同?

6 个答案:

答案 0 :(得分:37)

  • 编程:编写一个创建,转换,过滤,聚合和操作数据的程序。
  • 元编程:编写一个程序,用于创建,转换,过滤,聚合和操作程序
  • 通用编程:编写一个创建,转换,过滤,聚合和操作数据的程序,但只对数据结构做出最小限度的假设,从而最大限度地重复使用数据类型。

正如其他几个答案中已经提到的那样,区别在C ++中可能会引起混淆,因为通用编程和(静态/编译时)元编程都是通过模板完成的。为了进一步混淆你,C ++中的泛型编程实际上使用元编程是有效的,即模板专业化从通用编程生成专门的(快速)程序。

另请注意,正如每个Lisp程序员都知道的那样,代码和数据是相同的,所以实际上没有“元编程”这样的东西,它只是编程。同样,这在C ++中有点难以理解,因为您实际上使用两种完全不同的编程语言进行编程(C ++,C系列中的命令式,过程式,面向对象语言)和元编程(模板,纯功能“偶然) “语言介于纯lambda演算和Haskell之间,语法粗糙,因为它实际上并不打算编程语言。)

许多其他语言在编程和元编程时使用相同的语言(例如Lisp,Template Haskell,Converge,Smalltalk,Newspeak,Ruby,Ioke,Seph)。

答案 1 :(得分:13)

从广义上讲,元编程意味着编写可以产生其他程序的程序。例如。像C ++中的模板只在实例化时生成实际代码。可以将模板解释为将类型作为输入并生成实际函数/类作为输出的程序。预处理器是另一种元编程。元编程的另一个组成例子:一个程序,它读取XML并根据XML生成一些SQL脚本。同样,一般来说,元程序是一个产生另一个程序的程序,而泛型程序则是参数化(通常是其他类型)类型(包括函数)。

在考虑对此答案的评论后编辑

答案 2 :(得分:8)

我会粗略地将元编程定义为“编写程序编写程序”,将通用编程定义为“使用语言功能编写参数或参数的数据类型参数化的函数,类等”。

通过此标准,C ++模板对于通用编程(思考vectorlistsort ...)和元编程(想想Boost和例如Spirit)非常有用。此外,我认为C ++中的泛型编程(即编译时多态)是通过元编程实现的(即从模板化代码生成代码)。

答案 3 :(得分:5)

通用编程通常指的是可以使用多种类型的函数。例如。一个sort函数,它可以对一组可比较的数据进行排序,而不是对一个排序函数进行排序,以对一个int数组进行排序,另一个函数对一个字符串向量进行排序。

元编程是指以编程方式检查,修改或创建类,模块或函数。

答案 4 :(得分:4)

最好看其他语言,因为在C ++中,单一功能支持通用编程和元编程。 (模板非常强大)。

在Scheme / Lisp中,您可以更改代码的语法。人们可能认为Scheme是“带有大量括号的前缀语言”,但它也有非常强大的元编程技术(Hygenic Macros)。特别是,try / catch可以创建,甚至可以将语法操作到一个点(例如,如果你不想再编写前缀代码,这里是中缀转换器的前缀: http://github.com/marcomaggi/nausicaa)。这是通过元编程实现的,代码编写代码编写代码。这对于尝试新的编程范例很有用(AMB操作员在非确定性编程中起着重要作用。我希望AMB在未来5年左右成为主流......)

在Java / C#中,您可以通过泛型进行泛型编程。您可以编写一个支持许多其他类的类型的泛型类。例如,在Java中,您可以使用Vector来创建整数向量。或者Vector,如果你想让它特定于你自己的班级。

当事情变得奇怪的是,C ++模板是为通用编程而设计的。但是,由于一些技巧,C ++模板本身就是完整的。使用这些技巧,可以通过元编程为C ++语言添加新功能。它令人费解,但它确实有效。这是一个通过模板向C ++添加多个调度的示例。 http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html。更典型的例子是编译时的斐波纳契:http://blog.emptycrate.com/node/271

答案 5 :(得分:0)

通用编程是一种非常简单的元编码形式,尽管通常不是运行时。它更像是C中的预处理器,在大多数用例和基本实现中更多地涉及模板编程。

您经常会在键入的语言中找到您创建的一些实现,其中只有类型,如果不同。在诸如Java之类的语言中,由于每个类和接口都定义了一种新类型,因此这可能特别痛苦。

您可以通过将这些类转换为字符串文字然后将类名替换为要插入的变量来生成这些类。

在运行时使用泛型时,它有点不同,在这种情况下,它只是变量编程,使用变量编程。

设想的方法很简单,将文件,比较它们并将任何不同的东西变成变量。现在您只有一个可重用的文件。您只需要指定不同的名称,即名称变量。

泛型是如何产生的,并非所有东西都可以像你期望的变量类型或者类型一样变量。通常会有很多文件重复,其中唯一可变的是变量类型。这是一个非常常见的重复来源。虽然有各种各样的方法或减轻它,但它们并不是特别方便。泛型作为一种变量变量出现,允许变量类型变量。因为变量类型是通常在编程语言中表达的,现在可以在运行时指定,它也被认为是元语码,虽然这是一个非常简单的情况。

在您需要的地方没有可变性的影响是展开您的变量,即您被迫而不是使用变量来为每个可能的变量值实现变量。

你可以想象这是非常昂贵的。当使用任何类型的重用对象存储库时,这将是非常常见的。这些将接受任何对象,但在大多数情况下,人们只想要一种类型的objdct。如果你放入一个扩展Object的Shop对象然后想要检索它,那么存储对象上的方法签名将只返回Object,但你的代码将需要一个Shop对象。除非你把它重新投入商店,否则这会打破对象降级的编译。这引发了另一个难题,因为没有泛型,就无法检查兼容性并确保您存储的对象是Shop类。

Java避免了元编程,并尝试使用OOP多态原理来简化语言,而不是制作灵活的代码。然而,有一些紧迫和反复出现的问题,通过经验表现出来,并通过增加最少的元编程设施来解决。 Java不希望成为一种元编程语言,而是从那里谨慎地引入概念来解决最棘手的问题。

提供灌洗元编码功能的编程语言可以比语言更有效率,而不是禁止特殊情况,反射,OOP多态等等。但是,通常还需要更多的技能和专业知识来生成不可理解,可维护和无bug代码。对于这些语言而言,这些语言通常也会受到性能损失,因为C ++会被编译为原生语言。