メタプログラミングとは、プログラムが自分自身についての知識を持ち、自分自身を操作できるさまざまな方法を指します。
C# などの言語では、プログラムが自分自身についての情報を調べることができるので、リフレクションはメタプログラミングの一種と言えます。 例えば、オブジェクトのすべてのプロパティのリストを返す。
ActionScriptのような言語では、eval(“x” + i)のような新しいプログラムを作成するために、実行時に関数を評価することができます。 DoSomething()は、iが1のときはx1、iが2のときはx2というオブジェクトに影響を与えるだろう。
最後に、メタプログラミングの別の一般的な形態は、プログラムが自明ではない方法で自分自身を変更できるときである。 LISP はこの点でよく知られており、10 年ほど前に Paul Graham が唱えたものです。 彼の具体的なエッセイを調べてみる必要がありそうです。 しかし、このアイデアは、プログラムがその状態に応じて別の部分を変更するというものだ。 これは、今日のほとんどの一般的な言語では非常に困難な、実行時に決定を下す柔軟性のレベルを可能にします。
また、ストレートアセンブリでプログラミングしていた古き良き時代には、実行時に自身を変更するプログラムが必要で、非常に一般的だったことも注目に値します。
ポール グラハムの「Lisp は何で違っていたか」というエッセイより:
多くの言語にはマクロというものがあります。 しかし、Lisp のマクロはユニークです。 そして、信じられないかもしれませんが、それらが行うことは、括弧に関連しています。 Lispの設計者は、ただ単に他と違うという理由で括弧を入れたわけではありません。 BlubプログラマにはLispのコードは奇妙に見えるのです。 しかし、あの括弧には理由があるのです。 LispのコードはLispのデータオブジェクトからできています。 ソースファイルに文字が含まれていて、文字列は言語がサポートするデータ型の1つであるという些細な意味ではない。 Lisp のコードは、パーサーによって読み込まれた後、トラバースできるデータ構造でできています。
コンパイラの動作を理解していれば、実際に起こっていることは、Lisp が奇妙な構文を持っているというよりも、Lisp が構文を持っていないということです。 他の言語がパースされたときにコンパイラの中で生成されるパースツリーにプログラムを書くのです。 しかし、この解析木はあなたのプログラムから完全にアクセス可能です。 解析木を操作するプログラムも書けます。 Lispでは、このようなプログラムをマクロと呼びます。 5021>
プログラムを書くプログラムですか? いつそんなことをしたいのでしょうか。 Cobolで考えるなら、あまりないでしょう。 Lispで考えるなら、いつでも。 ここで、強力なマクロの例をあげて、ほら!これはどうだ!と言えると便利なんですが。 でも、そんなことをしても、Lispを知らない人にはちんぷんかんぷんでしょうし、その意味を理解するために必要なことをすべて説明する余裕はここにはないでしょう。 Ansi Common Lispでは、できるだけ速く物事を進めようとしましたが、それでも160ページまでマクロにたどり着けませんでした。
しかし、説得力のあるような議論をすることはできると思います。 Viaweb エディタのソースコードは、おそらく 20 ~ 25% ほどがマクロでした。 マクロは普通の Lisp 関数より書きにくいし、必要のないときに使うのはスタイルが悪いとされています。 ですから、そのコードに含まれるすべてのマクロは、そうでなければならないために存在しているのです。 つまり、このプログラムのコードの少なくとも20-25%は、他の言語では簡単にできないことをやっているということです。 Blubのプログラマーが、Lispの神秘的な力についての私の主張に対して懐疑的であったとしても、このことは彼に興味を抱かせるに違いない。 私たちは、このコードを自分たちの楽しみのために書いていたわけではありません。 私たちは小さなスタートアップで、競合他社との間に技術的な障壁を築くために、できる限り一生懸命プログラミングしていました。 私たちのコードの大部分は、他の言語では非常に困難なことを行っていました。 その結果、競合他社のソフトウェアではできないことができるようになったのです。 もしかしたら、何らかの関係があったのかもしれません。 その糸をたどってみることをお勧めします。 松葉杖をついて歩いているあの老人には、見た目以上のものがあるのかもしれません。