「同図像性」または「ホモイコニシティ(Homiconicity)」とは、プログラミング言語の性質の一つで、その言語のプログラムコードが、その言語自体のデータ構造として表現されることを指します。
「同図像性」は、「コードをデータとして扱う」言語という言葉でまとめられることが多い。例えばLISPのS式とか
一般に引用される例としてLispがある。Lispはリストの操作を容易にするために作られ、構造はネストしたリストの形をとるS式によって与えられ、他のLispコードによって操作することができる。他の例として、プログラミング言語Clojure(Lispの現代方言)、Rebol(またその後継Red)、Refal、Prolog、またおそらくJulia(詳細は「実装方法」セクション参照)である。
(define circle-area (lambda (r) (* 3.141592653 (* r r))))
原典は論文「Macro Instruction Extensions of Compiler Languages (コンパイラ言語のマクロ命令拡張)」で、初期の影響力のある論文「TRAC, A Text-Handling Language」によれば、以下の通りである。
主な設計目標の1つは、TRACの入力スクリプト(ユーザが入力するもの)は、TRACプロセッサの内部動作を導くテキストと同一であるべきというものでした。言い換えれば、TRACの手続きはユーザがキーボードで入力した通りの文字列としてメモリに保存されるべきです。また、TRACプロシージャ自体が新しいプロシージャを進化させる場合は、その新しいプロシージャも同じスクリプトで記述します。TRACプロセッサの動作では、このスクリプトを自分のプログラムとして解釈します。つまり、TRACトランスレータプログラム(プロセッサ)は、コンピュータを新しいプログラム言語(TRAC言語)を持つ新しいコンピュータに効果的に変換するのです。プログラムまたは手続き情報を、TRACプロセッサが実行中に作用するのと同じ形式でいつでも表示できることが望ましい。内部文字コード表現が外部コード表現と同じか、非常に似ていることが望まれます。現在のTRACの実装では、内部文字表現はASCIIをベースにしています。TRACの手続きとテキストはプロセッサの内部と外部で同じ表現をするので、同じという意味のhomoと表現を意味するiconから、homoiconicという用語が適用されます。
LISPとTRACとアランケイ
Alan Kayは1969年の博士論文で「ホモイコニック」という言葉を使い、おそらく一般化した。
これまでのすべてのシステムの例外として注目すべきは、Interactive LISP [...] とTRACです。どちらも機能指向で(一方はリスト、他方は文字列)、一つの言語でユーザと対話し、その内部と外部の表現が本質的に同じという意味で「ホモイコニック」である。また、新しい関数を動的に生成することができ、それをユーザーが自由に拡張することができる。唯一の欠点は、この言語で書かれたプログラムが、バビロニア文字で書かれたシュメール人へのバーニブラヒ王の手紙のように見えることだ。

:(s,fibo,(
:(ei,<1>, 1, 0,(
:(ei,<1>, 2, 1,(
:(aa, :(ri,fibo,:(as, <1>,1)),:(ri,fibo,:(as, <1>,2)))
))
))
))`
:(mw,fibo)'
ホモイコニシティの利点は、コードを表すデータをプログラムのメタ層とベース層の間で受け渡しできるため、新しい概念で言語を拡張することが一般的に容易になることである。関数の抽象構文木をメタ層でデータ構造として構成・操作し、それを評価することができる。コードを単純なデータとして理解することができるため(言語の形式自体がデータ形式であるため)、操作方法をより簡単に理解することができる。
ホモイコニシティの典型的な例として、メタ円形評価器がある。
メタ循環評価器 (MCE) またはメタ循環インタプリタ (MCI) は、インタプリタのホスト言語の同様の機能を使用して、解釈言語の各機能を定義するインタプリタである。例えば、ラムダアプリケーションの解釈は関数アプリケーションを使って実装されることがある。メタ循環評価はLispの文脈で最も顕著である。 自己インタープリタは、解釈言語がホスト言語とほぼ同一であるメタ循環インタープリタであり、2つの用語はしばしば同義的に用いられる
FACTOR
FactorはSlava Pestov氏によって作られたスタック指向のプログラミング言語です。Factorは動的型付けと自動メモリ管理、そして強力なメタプログラミング機能を備えています。この言語には、セルフホスト型の最適化コンパイラと対話的な開発環境を特徴とする単一の実装があります。Factorの配布には、大規模な標準ライブラリが含まれています。
今日の汎用コンピュータの大部分を含むフォン・ノイマン・アーキテクチャのシステムはすべて、生のマシンコードがメモリ上で実行され、データ型がメモリ上のバイトであることから、暗黙的にホモイコニックと表現することができる。しかし、この特徴はプログラミング言語レベルにまで抽象化することができる。
Lispやその方言、Scheme、Clojure、Racketなどの言語では、S式を用いてホモイコニティを実現している。
Rebolとダグラスクロックフォード
JavaScriptの開発で知られるDouglas Crockford氏は、Rebolを「より現代的な言語だが、プログラムとして実行可能なデータ表現に基づくという点で、Lispと非常に似た考えを持つ」と述べ、JSONに影響を与えた言語の一つであるとしている
RedとRebol
Redの構文と意味論はRebolのそれに非常に近い。Rebolと同様、メタプログラミングとドメイン特化言語(DSL)を強力にサポートし、したがって弁証法(組み込みDSLの作成)のための非常に効率的なツールである。RedにはRed/Systemという方言があり、これはシステムプログラミング機能を提供するCレベルの言語です。RedはDLL(libRed)として他のツールや言語との統合が容易で、非常に軽量(1MB程度)です。また、様々なプラットフォームへのクロスコンパイル(後述のクロスコンパイルの項を参照)や、それを必要とするプラットフォーム用のパッケージの作成(例:Androidの.APK)が可能です。また、Red は、基盤となる反応型データフローエンジンに基づく完全に反応型のクロスプラットフォーム GUI システム、SVG と同等の 2D 描画弁、コンパイル時および実行時のマクロサポート、40 種類以上の標準データ型も備えています。
セクシーからSNOBOLへ
Dave Farberによると[15]、彼とGriswoldとPolonskyは「最終的にSymbolic EXpression Interpreter SEXIという名前にたどり着いた」そうだ。
ある日、私はシステムを組み立てるバッチジョブを送信していたのですが、通常通り、デッキの最初のカードであるJOBカードに、BTL標準で自分のジョブと自分の名前、SEXI Farberと打ち込みました。
それを見たコンプセンターの女の子が、ユーモアを交えて「そういうことか」と言ったんです。
それで、もう一人名前が必要だということがはっきりしたんです! 私たちは座って話をし、コーヒーを飲み、輪ゴムを打ち、あまりに長い時間が過ぎた後、誰かが -- おそらくラルフでしょうが -- 「私たちが名前を見つけるチャンスは地獄の雪だるまのようにない」と言いました。私たち全員が一斉に「WE GOT IT -- SNOBOL」と、BOL言語の精神に則って叫びました。そして、「SNOBOL」が何を表しているのか、頭をひねった。
SNOBOL」の一般的なバッククロニムは、「String Oriented SymBOlic Language」[16]、あるいは(準初期主義として)「StriNg Oriented symBOlic Language」である。
本命Refal
Refal (Recursive functions algorithmic language、ロシア語: РЕФАЛ) は、「文字列処理、言語翻訳、人工知能」などの「記号計算を指向する」関数型プログラミング言語である。Refalは数学的な単純さと、大規模で洗練されたプログラムを書くための実用性を併せ持つことを意図していた。
関数型プログラミング言語の先駆けであり、当時のLispとは異なり、Refalはパターンマッチングをベースにしている。そのパターンマッチングは項書換えと連動している。
LispやPrologの基本的なデータ構造は、cons演算によって順次構築される線形リストであり、リストのn番目の要素へのアクセスはO(n)である。Refalのリストは両端からスキャンされ、最上位のリストだけでなく、ネストされたリストに対してもパターンマッチが働きます。事実上、Refalの基本的なデータ構造はリストではなくツリーである。これにより、パターンマッチと代入という数学的に単純な制御機構のみを用いながら、データ構造の作成に自由度と利便性を持たせている。
また、Refalは効率的な部分評価をサポートするためにフリーザという機能を備えている。

記号、シンボル、変数 8. プログラム生成例
Refal言語によるプログラム例 . 9. Refalにおけるアルゴリズムの等価変換 .
式、関数、識別 10. 有限体における計算
リフロープログラムの実行 11. トランスポーズ
構造用ブラケット。差別化 12.ステートメントロジック操作
標準機能です。 13. 多項式に作用する。
リフロープログラムのモジュール付録1.Refala-5の標準機能一覧 (V. Turchin)
付録2.リファール5(Ark.クリモフ)
メタコンピューティングとは、計算機Mから、Mの働きを制御・解析・模倣するメタマシンM'へのメタシステム遷移(MST)を伴う計算のことで、部分評価やスーパーコンパイル(SCP)などのセマンティックベースのプログラム変換はメタコンピューティングである。メタシステム遷移は、プログラム変換器が変換されるときのように繰り返されることがある。このようにして、任意の高さのMST階層を形成することができる。
1970年代に二村善彦によって初めて記述された部分評価の使用例[1]の中で特に興味深いのは、progがプログラミング言語のインタプリタである場合である。
Istatic がそのインタープリタの内部で動作するように設計されたソースコードである場合、このデータ/プログラムに対するインタープリタの部分評価は、そのソースコードのみを実行し、インタープリタの実装言語で書かれ、ソースコードの再供給を必要とせず、インタープリタとソースの元の組み合わせよりも速く実行するインタープリタのバージョン、progを生成します。この場合、progは事実上、Istaticのコンパイル版である。
この手法は、第一次二村式と呼ばれ、3つある。
与えられたソースコードに対してインタープリタを特化し、実行形式を得る。
インタプリタに特化したスペシャライザ(1.で適用)、コンパイラを生成する。
自分自身のためにスペシャライザーを特化させる(#2で適用)ことで、任意のインタープリターを同等のコンパイラーに変換できるツールを得る。
1983年、二村が初めて発表した。
1993年の夏、二村は私を東京に招き、彼の一般化部分計算 [10,11] の概念に関連してスーパーコンピューティングを議論するために一ヶ月間滞在させた。確かに共通する部分がある。どちらのアプローチでも、計算機の状態に関する情報は、いくつかの変数の値を列挙する以上のものである。主な違いは、二村が不特定多数の定理証明に依存しているのに対し、私の主張は定理証明も含めてすべてを超コンパイルで行うことである。
「LISP 1.5 Programmer's Manual」に書かれているLispインタプリタのコードを読み解いて、Lispコンパイラをプログラミングする、という仕事から得た、インタプリタを入力するとコンパイラが出力されるコンパイラジェネレータはコンピュータのプログラムとして作れるのではないかという着想を、それらの処理系の関係は「自己適用可能な部分評価系」を利用してエレガントに定式化できる、という美しい理論に結実させた(1971年)[1]。この定式化は後に、アンドレイ・エルショフ(英語版)が「二村の射影」と呼ばれるべき、と讃え(式のどの部分が、なぜ「射影」であるのか、といった詳細については、部分評価#二村射影を参照)、理論計算機科学の重要な成果とされている。1973年、ハーバード大学応用数学科大学院修士課程修了
ちょっとした秘密を明かします。私たちのスーパーコンピュータは、実はオブジェクトプログラムの言語としてRefalを使っているのではなく、パターンマッチンググラフの言語(Refalグラフとも呼ばれる)を使っているのです。スーパーコンピュータの対象となるRefalのプログラムは、まずグラフ形式に自動変換され、SCPの出力もRefalグラフとなる。