2017-11-02 17 views
0

は、ここで私は最初のものをmacroexpandingで clojureはコンパイル時にどのようにコードを評価しますか?

(defmacro hello [x] (eval '(+ 1 2)))

&

(defmacro hello [x] '(+ 1 2))

を書いていた二つのマクロです、私は (+ 1 2)を取得し、第二のmacroexpandingながら、私は値3を取得します。これはコンパイル時に追加が行われたことを意味しますか?どのようにそれは可能ですか? '(+ 1 2)の代わりに、私はdbを照会する関数を書いていました。それはコンパイル時にデータベースに問い合わせますか?

答えて

7

マクロは任意のコードをコンパイラに挿入します。通常、目的は(1 + 2)のようなカスタムコードを "前処理"して、Clojureが(+ 1 2)のように理解できるようにすることです。しかし、本当にしたい場合は何か(DBアクセスを含む)をコンパイル段階に含めることができます。結局のところ、コンパイラは汎用コンピュータ上で動作する単なるソフトウェアに過ぎません。オープンソースなので、コンパイラコードを直接変更して何かを行うことができます。

マクロを使用すると、コアClojure言語を拡張するために最適化されたベースコンパイラコードを変更/拡張する便利な方法です。ただし、マクロはそのユースケースに限定されません(本当に夢中ならば)。


Turing CompleteコンパイラプリプロセッサであるC++式テンプレートメカニズムを使用する同様の機能があります。有名な例は、コンパイラを使用して最初のいくつかの素数を「エラー」メッセージとして計算することでした。 http://aszt.inf.elte.hu/~gsd/halado_cpp/ch06s04.html#Static-metaprogramming

2

マクロ本体がコンパイル時に実行され、その戻り値がコード内の使用法を置き換えるために使用され、この新しいコードがコンパイルされます。

したがって、マクロコード:

(defmacro hello [x] (eval '(+ 1 2)))

は、実際にコンパイル時にフォーム'(+ 1 2)evalを実行するとその発現(3)の結果値は、その使用を交換マクロの結果として返されます(例えば、(hello 0))。

+0

今私は力を見る:D –

関連する問題