2017-01-14 11 views
1

私は、Clojureのマクロを、htmlマクロの上に使いたいと思っています。これに展開するだろう...Clojureマクロでは、どのように自動名を同一にするか?

​​

:今、私はこのように使用され、マクロを記述する必要が

(def app ^:dynamic {}) 

(def-page app 
    [:page/not-found [{path :path}] 
    [:path] (content path)]) 

(def-page app 
    [:page/other-page [{x :x}] 
    [:x] (content x)]) 

私の試みはこれです:

(defmacro def-app [pages] 
    `(do 
    (def app# ^:dynamic {}) 

    [email protected](for [page# pages] 
     `(def-page app# ~page#)))) 

..これに展開する:

(do (def app__3251__auto__ {}) 
    (user/def-page app__3250__auto__ [:page/not-found [{path :path}] [:path] (content path)]) 
    (user/def-page app__3250__auto__ [:page/other-page [{x :x}] [:x] (content x)])) 

... OK lmost二つのものを除い:

  1. 名アプリ#は^ 2人の異なる名前
  2. に展開:ダイナミックは

2番目の結果から欠落している実際には問題はありませんが、私はなぜそれが起こるのだろうか?

おかげ#で作成

答えて

2

gensymのは、彼らが作成された構文の引用で再利用可能なだけです。これは、あまりにも拡大

(defmacro def-app [pages] 
    (let [app (gensym "app")] 
    `(do 
     (def ~app ^:dynamic {}) 
     [email protected](for [page# pages] 
      `(def-page ~app ~page#))))) 

:次のようにあなたがgensymへの明示的な呼び出しを使用することができます生成されたシンボルを再利用するに^:マクロ読者は、マクロの前に読まれているため

(do (def app22770 {}) 
    (user/def-page app22770 [:page/not-found [{path :path}] [:path] (content path)]) 
    (user/def-page app22770 [:page/other-page [{x :x}] [:x] (content x)])) 

次に、^:dynamicがありません拡張コンパイラ段階。私たちは、生成されたvarが動的であることがわかります

(defmacro def-app [pages] 
    (let [app (gensym "app")] 
    `(do 
     (def ~(vary-meta app merge {:dynamic true}) {}) 
     [email protected](for [page# pages] 
      `(def-page ~app ~page#))))) 
;; => user/app23239 

(meta (var app23239)) 
;; => {:dynamic true (...) } 
ダイナミックVARを生成する機能 vary-metaまたは with-metaを使用します
関連する問題