元编程(Metaprogramming)是指某类
计算机程序的编写,这类计算机程序编写或者操纵其他
程序(或者自身)作为它们的数据,或者在运行时完成部分本应在
编译时完成的工作。很多情况下与手工编写全部代码相比工作效率更高。编写元程序的语言称之为
元语言,被操作的语言称之为
目标语言。一门语言同时也是自身的元语言的能力称之为反射。
反射是促进元编程的一种很有价值的语言特性。把编程语言自身作为头等对象(如Lisp或Rebol)也很有用。支持
泛型编程的语言也使用元编程能力。
元编程通常有两种方式起作用。一种方式是通过
应用程序接口(API)来暴露运行时引擎的内部信息。另一种方法是动态执行包含编程命令的字符串。因此,“程序能编写程序”。虽然两种方法都能用,但大多数方法主要靠其中一种。
LISP语言是元编程的典型,在20世纪70年代到80年代间十分流行,尤其是在人工智能领域。C++的元编程(确切的说是范型编程 generic programming)在1994年初露端倪,由一个叫 Erwin Unruh 的人首先发现。在1994年,C++标准委员会在圣迭戈(SanDiego)举行的一次会议期间, Erwin Unruh展示了一段特别的代码。这段代码的特别之处在于程序的功能在编译期实现而非运行期,
编译器以错误信息的方式产生从2到某个给定值之间的所有
质数。同年夏天, Todd Veldhuizen 受Erwin 的例子启发,发现可以使用C++模板进行元编程,并发表了一份技术报告。
这个脚本(或程序)生成了一个新的993行程序来打印1至992。这只是演示用代码来写更多代码,并不是打印数字的最有效方法。然而,一个程序员可以几分钟内编写和执行
元程序,却生成了近1000行代码。
该示例定义了一个
类模板,类中声明了一个
枚举类型,该程序的奥秘就在枚举类型的构造上。从枚举类型的构造可以看出,他自身有一个样隐含的
迭代计算。两个
构造函数为枚举类型初始化了数列的初始值,当调用“Fibonacci<20>::Reasult“时,就以这两个初始值为基础进行
迭代。因此,程序在运行时并没有显示的计算,而是在编译时就由
编译器计算了。
当编译器实例化Fibonacci<20>时,为了给其enum Result赋值,编译器需要对Fibonacci<19>和Fibonacci<18>进行实例化,之后同理······,当实例化到Fibonacci<1>和Fibonacci<0>的时候,完全特化模板被实例化,至此迭代结束。
在Ruby中,最常用的就是attr系列方法,譬如attr、attr_reader、attr_writer、attr_accessor。attr_reader方法为一个
实例变量产生一个用于读取其值的方法,attr_writer为其产生一个用于写入值的方法,attr_accessor则同时具有这两种功能。
最常用的元编程工具是
编译器,把高级语言转换为
汇编语言或
机器语言。更灵活的方法是在程序中嵌入
解释器直接处理程序数据。有一些实现例如为Object Pascal编写的RemObject's Pascal Script。
面向语言的程序设计是一种强烈关注元编程的编程风格,通过
领域特定语言来实现。