簡介
在計算機編程中,同像性(homoiconicity,來自希臘語單詞 homo,意為與符號含義表示相同)是某些程式語言的特殊屬性,它意味著一個程式的結構與其句法是相似的,因此易於通過閱讀程式來推測程式的內在涵義。如果一門程式語言具備了同像性,說明該語言的文本表示(通常指原始碼)與其抽象語法樹(AST)具有相同的結構(即,AST 和語法是同形的)。該特性允許使用相同的表示語法,將語言中的所有代碼當成資料,來存取以及轉換,提供了“代碼即數據”的理論前提。
同像語言中,程式的主要呈現方式,也是語言本身原始類型中的數據結構。這使得元編程(metaprogramming)更加容易,因為程式代碼可以被視為資料:語言中的反射(運行時檢查程式的實體)取決於單一的、性質相同的結構,而且它不必去處理,其它一些不同結構所導致的複雜語法。換句話說,同像性是程式的原始碼即是基本的數據結構,而這個語言本身知道如何存取源碼的文本。
Lisp程式語言是具有同像性質的典型範例。它的設計很容易進行對列表的操作,而且其語法結構即採用嵌套列表形式的S-表達式。LISP 程式以列表的形式來編寫; 所以可在運行時存取本身擁有的函式和程式,並以編程的方式重新設計自己。具有同像屬性的語言通常有對句法宏的全面支持,允許程式設計師以簡明的方式來表達程式的變換。這類語言有 Clojure(現代流行的 LISP 方言),Rebol 和 Refal,以及最近的 Julia 等等程式語言。
歷史
同像性一詞的原始來源是論文《編譯器語言的宏指令擴展》。根據早期具影響力的論文《TRAC,文本處理語言》中提到: “主要設計目標之一是TRAC的輸入腳本(用戶所輸入的)應該與指示TRAC處理器內部動作的文本相同一致。換句話說,TRAC程式應該是以字串被儲存於記憶體中,正如同用戶在鍵盤上鍵入它們一樣。如果TRAC程式本身發展成為新的程式,同一個腳本中也應該陳述列出這些新程式。TRAC處理器在其操作中將此腳本直譯為其程式。換句話說,TRAC解析器(處理器)有成效地將計算機轉換為具有新程式語言(TRAC 語言)的新計算機。程式或過程資訊在任何時候的呈現,都應該相同於TRAC處理器執行期間對其作用的形式。我們期望內部代碼的字元表示,和外部代碼表示相同一致或非常相似。在本TRAC實作中內部字元立基於ASCII,因為TRAC程式和文本在處理器內部和外部都具有相同的表示,所以術語同像性一詞是適用的,從涵義相同於符號呈現的意義。”
依照道格拉斯·麥克羅伊的提議,依據Peirce,C.S.McIlroy M.D.的術語,“編譯器語言的宏指令擴展”,ACM通訊,頁214-220; 1960年4月。
艾倫·凱在他1969年的博士論文中使用並可能推廣了同像性這個術語: “所有先前的系統之外,顯著的一組例外是Interactive LISP[...]和TRAC。兩者都是函式導向的(一為列表,另一為字元串),都用一種語言與用戶交談,並且都具有 “同像性的”,因為它們內部和外部表示本質上相同。它們都具有動態創建新函式的能力,然後可隨著用戶的興趣進階發展。他們唯一最大的缺點是,以它們寫出的程式看起來像是蘇美人把Burniburiach國王的信寫成巴比倫楔形文!”
優缺點
同像性的一個優點是,以新概念擴展語言通常變得更簡單,因為表示代碼的資料可在程式的元和基本層之間傳遞。函式的抽象語法樹可以作為元層中的數據結構來組成和操作,然後被評估。它可以更容易理解如何操作代碼,因為它可以被理解為簡單的資料(語言本身的格式亦同為資料格式)。
允許這樣做的簡單性也帶來了一個缺點:一個部落格認為,至少在類似LISP的列表導向的語言的情況下,它會消除許多能幫助人們分析語言結構的視覺線索,而可能導致陡峭的學習曲線。