2012-02-07 12 views
1

clojureでは、マクロはプログラマに大きな力を与えます。 evalも非常に強力です。両者には微妙な違いがあります。私は、この謎がこの話題を明るく照らしてくれることを願っています。 1は、例外が発生し、なぜ他のものにはないrun-stuff体、内部に3文以上Clojure riddle:eval、macros、およびnamespace

(ns hello) 
(defmacro my-eval [x] `~(read-string x)) 
(defn hello[] "Hello") 
(defn run-stuff [] 
    (println (hello)) 
    (println (my-eval "(hello)")) 
    (println (eval (read-string "(hello)")))) 
(ns main) 
(try (hello/run-stuff) 
    (catch Exception e (println e))) 

私はこの美しい質問Clojure - (read-string String calling functionの調査に続いて、次のような謎を定式化しました。説明のための@Matthias Benkardのおかげで、

答えて

4

(println (hello))(println (my-eval "(hello)"))は全く同じステートメントです。唯一の違いは、あなたのエディタをもっと混乱させるということです。 my-evalは実際のevalに匹敵しません。相違点は、my-evalへの引数は、コンパイル時に文字列である必要があることです。記号xを文字列にキャストできないため、次のエラーが出力されます。

(def x "(hello)") 
(my-eval x) 

これはmy-evalは全く無意味になり - あなたは「evalの」文字列リテラルをしたり、(自分のエディタが理解すること)引用符とmy-evalを削除し、同じように機能コードを持つことができます。一方、evalは、実行時にコードをコンパイルしようとします。ここでは、main名前空間から実行されているため、@Matthias Benkardが指摘しているように、それはhello名前空間ではなく失敗します。