元編程

元編程

元編程(Metaprogramming)是指某類電腦程式的編寫,這類電腦程式編寫或者操縱其他程式(或者自身)作為它們的數據,或者在運行時完成部分本應在編譯時完成的工作。很多情況下與手工編寫全部代碼相比工作效率更高。編寫元程式的語言稱之為元語言,被操作的語言稱之為目標語言。一門語言同時也是自身的元語言的能力稱之為反射。

基本介紹

  • 中文名:元編程
  • 外文名:Metaprogramming
  • 屬於:某類電腦程式的編寫
  • 語言特性反射
元編程的概念,發展,使用示例,

元編程的概念

反射是促進元編程的一種很有價值的語言特性。把程式語言自身作為頭等對象(如LispRebol)也很有用。支持泛型編程的語言也使用元編程能力。
元編程通常有兩種方式起作用。一種方式是通過應用程式接口(API)來暴露運行時引擎的內部信息。另一種方法是動態執行包含編程命令的字元串。因此,“程式能編寫程式”。雖然兩種方法都能用,但大多數方法主要靠其中一種。

發展

LISP語言是元編程的典型,在20世紀70年代到80年代間十分流行,尤其是在人工智慧領域。C++的元編程(確切的說是范型編程 generic programming)在1994年初露端倪,由一個叫 Erwin Unruh 的人首先發現。在1994年,C++標準委員會在聖迭戈(SanDiego)舉行的一次會議期間, Erwin Unruh展示了一段特別的代碼。這段代碼的特別之處在於程式的功能在編譯期實現而非運行期,編譯器以錯誤信息的方式產生從2到某個給定值之間的所有質數。同年夏天, Todd Veldhuizen 受Erwin 的例子啟發,發現可以使用C++模板進行元編程,並發表了一份技術報告。

使用示例

一個簡單元編程的例子是使用bash腳本的產生式編程示例:
#!/bin/bash
# metaprogram
echo '#!/bin/bash' >program
for ((I=1; I<=992; I++)) do
echo "echo $I" >>program
done
chmod +x program
這個腳本(或程式)生成了一個新的993行程式來列印1至992。這只是演示用代碼來寫更多代碼,並不是列印數字的最有效方法。然而,一個程式設計師可以幾分鐘內編寫和執行元程式,卻生成了近1000行代碼。
==========
C++中也可以使用模板來進行元編程(以下代碼在VC2008中編譯通過):
#include<iostream>
using namespace std;
int Result;
//主模板
template<int N> //模板
class Fibonacci
{
public:
enum{Result = Fibonacci<N-1>::Result + Fibonacci<N-2>::Result };
//枚舉,帶有隱含計算
};
//完全特化模板
template<>
class Fibonacci<1> //帶常參數1的構造函式
{
enum { Result = 1 };
//給枚舉賦初值1
};
//完全特化模板
template<>
class Fibonacci<0> //帶參數0的模板
{
public:
enum { Result = 0 };
//給枚舉賦初值0
};
int main()
{
std::cout << "第20項的Fibonacci數是:" << Fibonacci<20>::Result << std::endl;
//隱含計算
system("pause");
return 1;
}
該示例定義了一個類模板,類中聲明了一個枚舉類型,該程式的奧秘就在枚舉類型的構造上。從枚舉類型的構造可以看出,他自身有一個樣隱含的疊代計算。兩個構造函式為枚舉類型初始化了數列的初始值,當調用“Fibonacci<20>::Reasult“時,就以這兩個初始值為基礎進行疊代。因此,程式在運行時並沒有顯示的計算,而是在編譯時就由編譯器計算了。
當編譯器實例化Fibonacci<20>時,為了給其enum Result賦值,編譯器需要對Fibonacci<19>和Fibonacci<18>進行實例化,之後同理······,當實例化到Fibonacci<1>和Fibonacci<0>的時候,完全特化模板被實例化,至此疊代結束。
所以,該程式編譯的結果僅包含一個常量值,輸出如下:
第20項的Fibonacci數是:6765
==========
不是所有的元編程都用產生式編程。如果程式可以在運行時改變(如LispRubyPythonSmalltalkLuaGroovy和JavaScript),這種技術可以不實際生成原始碼就使用元編程。
在Ruby中,最常用的就是attr系列方法,譬如attr、attr_reader、attr_writer、attr_accessor。attr_reader方法為一個實例變數產生一個用於讀取其值的方法,attr_writer為其產生一個用於寫入值的方法,attr_accessor則同時具有這兩種功能。
class Foo
attr_reader :just_read
attr_writer :just_write
attr_accessor :both_read_and_write
def initialize
@just_read = 0
@just_write = 0
@both_read_and_write = 0
end
end
# 輸出attr系列方法生成的方法
puts Foo.instance_methods - Foo.superclass.instance_methods
最常用的元編程工具是編譯器,把高級語言轉換為彙編語言機器語言。更靈活的方法是在程式中嵌入解釋器直接處理程式數據。有一些實現例如為Object Pascal編寫的RemObject's Pascal Script。
另一個很常用的元編程例子是lex和yacc,用來生成詞法分析器語法分析器Yacc通常用作編譯器的編譯器,生成一個把高級語言轉換為機器語言的工具。
quine是一種原始碼等於輸出的特殊的元程式
面向語言的程式設計是一種強烈關注元編程的編程風格,通過領域特定語言來實現。
元編程

相關詞條

熱門詞條

聯絡我們