ある種のメタプログラミングを可能にする多くの言語があります。特に、言語のLispファミリーについて話している回答がないことに驚いています。
ウィキペディアから:
メタプログラミングとは、プログラムをデータとして扱うことができるコンピュータープログラムを作成することです。
本文の後半:
Lispはおそらく、歴史的な優先順位と、メタプログラミングの単純さと力のために、メタプログラミング機能を備えた典型的な言語です。
Lisp言語
Lispの簡単な紹介を次に示します。
コードを表示する1つの方法は、一連の指示としてです。これを実行し、それを実行し、次に他のことを実行します...これはリストです!プログラムが行うことのリスト。そしてもちろん、ループなどを表すためにリスト内にリストを持つことができます。
我々は、B、C、D、このような要素を含むリストを表現している場合:(ABCD)私たちは何かを得ることLispの関数呼び出しのようなルックスa
の機能である、とb
、c
、d
引数があります。実際、典型的な「Hello World!」プログラムは次のように書くことができます:(println "Hello World!")
もちろんb
、c
またはd
同様に評価するリストにすることもできます。次のように(println "I can add :" (+ 1 3) )
すると、「 "I can add:4"」と出力されます。
したがって、プログラムは一連のネストされたリストであり、最初の要素は関数です。良いニュースは、リストを操作できることです!したがって、プログラミング言語を操作できます。
Lispの利点
Lispはプログラミング言語ではなく、プログラミング言語を作成するためのツールキットです。プログラム可能なプログラミング言語。
これは、Lispで新しい演算子を作成するのがはるかに簡単であるだけでなく、関数に渡されるときに引数が評価されるため、他の言語でいくつかの演算子を書くこともほぼ不可能です。
たとえば、Cのような言語ではif
、次のような演算子を自分で記述したいとしましょう。
my-if(condition, if-true, if-false)
my-if(false, print("I should not be printed"), print("I should be printed"))
この場合、引数の評価の順序に依存する順序で、両方の引数が評価および出力されます。
Lispsでは、演算子(マクロと呼びます)の記述と関数の記述はほぼ同じことであり、同じ方法で使用されます。主な違いは、マクロへのパラメーターがマクロへの引数として渡される前に評価されないことです。これは、if
上記のようないくつかの演算子を書くことができるために不可欠です。
現実の言語
ここでは正確に示すことは少し範囲外ですが、詳細については1つのLispでプログラミングしてみることをお勧めします。たとえば、あなたは見てみることができます:
ああ、ところで、LispはLISt Processingを意味します。
あなたの例について
以下にClojureを使用した例を示します。
add
Clojure (defn add [a b] ...your-implementation-here... )
で関数を作成できる場合は、その+
ように名前を付けることができます(defn + [a b] ...your-implementation-here... )
。実際、これは実際の実装で行われていることです(関数の本体はもう少し複雑ですが、定義は上で書いたものと本質的に同じです)。
中置記法はどうですか?Clojureはprefix
(またはポーランド語)表記を使用しているため、infix-to-prefix
プレフィックス付きのコードをClojureコードに変換するマクロを作成できます。これは実際には驚くほど簡単です(実際、clojure koansのマクロ演習の 1つです)!野生でも見ることができます。たとえば、Incanter $=
マクロを参照してください。
ここに説明されている公案からの最も簡単なバージョンがあります:
(defmacro infix [form]
(list (second form) (first form) (nth form 2)))
;; takes a form (ie. some code) as parameter
;; and returns a list (ie. some other code)
;; where the first element is the second element from the original form
;; and the second element is the first element from the original form
;; and the third element is the third element from the original form (indexes start at 0)
;; example :
;; (infix (9 + 1))
;; will become (+ 9 1) which is valid Clojure code and will be executed to give 10 as a result
さらにポイントを進めるために、いくつかのLispの引用:
「Lispを際立たせるものの一部は、進化するように設計されていることです。Lispを使用して、新しいLisp演算子を定義できます。新しい抽象化が一般的になると(オブジェクト指向プログラミングなど)、常にLispで簡単に実装できるようになります。DNAのように、そのような言語はスタイルを失いません。」
—ポールグラハム、ANSI Common Lisp
「Lispでのプログラミングは、宇宙の原始的な力で遊ぶようなものです。指先の間を稲妻のように感じます。他の言語は親近感さえありません。」
— Glenn Ehrlich、Lispへの道