怎麼理解元編程?

常看到元編程這個字眼,怎麼理解元編程。希望別複製粘貼答案。


Meta- 這個前綴在希臘語中的本意是「在…後,越過…的」,類似於拉丁語的 post-,比如 metaphysics 就是「在物理學之後」,這個詞最開始指一些亞里士多德的著作,因為它們通常排序在《物理學》之後。

但西方哲學界在幾千年中漸漸賦予該詞綴一種全新的意義:關於某事自身的某事。比如 meta-knowledge 就是「關於知識本身的知識」,meta-data 就是「關於數據的數據」,meta-language 就是「關於語言的語言」,而 meta-programming 也是由此而來,是「關於編程的編程」。

弄清了詞源和字面意思,可知大陸將 meta- 這個前綴譯為「元」並不恰當。台灣譯為「後設」,稍微好一點點,但仍舊無法望文生義。也許「自相關」是個不錯的選擇,「自相關數據」、「自相關語言」、「自相關編程」——但是好像又太羅嗦了。

Anyway。先看看 meta-data:

「我的電話是 +86 123 4567 8910」

——這是一條數據;

「+86 123 4567 8910 有十三個數字和一個字元,前兩位是國家代碼,後面是一個行動電話號碼」 —— 這是關於前面那條數據的數據。

那麼照貓畫虎,怎樣才算 meta-programming 呢?泛泛來說,只要是與編程相關的編程就算是 meta-programming 了——比如,若編程甲可以輸出 A - Z,那麼寫程序甲算「編程」;而程序乙可以生成程序甲(也許還會連帶著運行它輸出 A - Z),那麼編寫程序乙的活動,就可以算作 meta-programming,「元編程」。注意,程序甲和程序乙並不一定是同一種語言:

("A".."Z").each do |char|
system("python -c "print "#{char}""")
end

如此說來,inline SQL 甚至動態生成 HTML 也是元編程了?摳定義的話是這樣吧。

不過 metaprogramming 更狹義的意思應該是指「編寫能改變語言語法特性或者運行時特性的程序」。換言之,一種語言本來做不到的事情,通過你編程來修改它,使得它可以做到了,這就是元編程。本版同文提及 method_missing,那麼 Wat —
Destroy All Software Talks 之中給出了運行時元編程的經典範例:

&>&> ruby has no bare words
NameError: undefined local variable or method `words" for main:Object
from (irb) 1
&>&> def method_missing(*args); args.join(" "); end
=&> nil
&>&> ruby has bare words
=&> "ruby has bare words"
&>&> bare words can even have bangs!
=&> "bare words can even have bangs!"

C、C++、Python、JavaScript…… 多數流行的語言或多或少都有元編程能力;Lisp 諸方言更是以元編程為基本。而 Ruby 更是因為元編程易用又強大,被許多人拿來寫 DSL,因為元編程可以捏出「本不存在的語法特性」來讓書寫 DSL 變得簡單。


翻譯的問題,怎麼看都搞不清楚這個元編程怎麼翻譯過來的

元編程就是編寫把要執行的代碼當文本進行操作的代碼,舉個不嚴謹的例子:

比如你要打從1到5五個數字,用python的話就是

print(1)
print(2)
print(3)
print(4)
print(5)

這就是正常編程

你還這以這麼做

for i in range(5):
print("print(" + str(i + 1) + ")")

然後把列印出來的結果當python代碼執行,同樣可以列印1到5,這就是元編程.


可以擴展程序自身,這樣的能力,為元編程。

比如Ruby,使用元編程可以擴展出領域專用語言DSL, 比如RSpec、puppet、chef等。相對於新創造的領域專用語言DSL來說, Ruby語言就成為其的元語言。

所以, 叫做元編程 。


元編程是用代碼在編譯期或運行期生成/改變代碼。除非程序的運行期的輸入數據會被直接或間接轉化成代碼,否則元編程不會給程序帶來新的邏輯(資訊理論原理),此時它本質上是一種(讓程序員自我感覺良好的)手工壓縮源代碼技術


meta-programming

一般代碼的操作對象是數據

元編程操作的對象是其他代碼


舉個例子:我們知道現在3D印表機可以列印各種東西,什麼桌椅啦,模型啦,甚至是手槍。

但是有個3D印表機比較特別,它能列印「3D印表機」!這個3D印表機就可以稱為「元3D印表機」!


就是無關業務邏輯,只跟當前代碼結構相關的代碼。比如通過在運行時通過java反射把所有Action結尾的類找出來,加上log或者其它動作。或者ruby里的methodingmissing, objc的category等給系統自帶的類增強一些特性等。共有的特性就是它們處理的對象是你的代碼,不是業務對象。


元編程之javascript ,祝你能找到答案。


you write code that writes code.


就是你寫的代碼是用來生成代碼的


有點跑題,不過意思類似,有共通的地方:

假如你用C語言寫了一個程序,有輸入有輸出,跑得很好。這就是編程了。

接著,考慮編譯了你這個程序的C編譯器。它輸入你的代碼,輸出一個可執行文件。如果你把這個編譯器寫出來,就差不多算是「元」了一層。

再考慮,有個「編譯器生成器」,可以輸入各種語言的描述,輸出該語言的編譯器。比如你把C的語法規則按某個格式輸進去,它就會吐出一個C編譯器出來。那麼如果把這個生成器寫出來,那差不多又「元」了一層。

嗯,其實我也不確定「元編程」這個術語是這個意思,所以,僅供參考,請勿當真。


非常贊同:"元編程"比"我們手寫代碼"多提供了一個抽象層次!用代碼中的元數據來進行動態插入新代碼邏輯!其實,也是根本沒有什麼「元編程」,有的只是「編程」。


根本就沒有元編程,有的只是編程而已

推薦看看《ruby元編程》


前面各位已經說的很好了,我的理解是

"元編程"比"我們手寫代碼"多提供了一個抽象層次

貼一篇我認為寫的不錯的文章

Ruby元編程構造簡單優雅解決方案


推薦閱讀:

這種前端架構好嗎?
js到底應該由誰來寫?
Web前端需要熟悉大學裡[高大上]計算專業課嗎?
chrome開發者工具提示準確性的問題?
怎樣測試頁面載入時間?

TAG:前端開發 | JavaScript | Ruby | Python | 編程 |