通用编程与元编程

问题描述 投票:17回答:6

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

除了C的过程编程风格之外,C ++还直接支持某些形式的面向对象编程,泛型编程和元编程。

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

programming-languages metaprogramming generic-programming
6个回答
37
投票
  • 编程:编写一个程序,用于创建,转换,过滤,聚合和操作数据。
  • 元编程:编写一个程序,用于创建,转换,过滤,聚合和操作程序。
  • 通用编程:编写一个创建,转换,过滤,聚合和操作数据的程序,但只对数据结构做出最小限度的假设,从而最大限度地重用各种数据类型。

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

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

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


13
投票

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

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


8
投票

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

通过这个标准,C ++模板对于泛型编程(想想vectorlistsort ......)和元编程(想想Boost和例如Spirit)都很有用。此外,我认为C ++中的通用编程(即编译时多态性)是通过元编程(即从模板化代码生成代码)来完成的。


5
投票

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

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


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


0
投票

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

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

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

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

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

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

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.