2017-04-10 4 views
1

は、私は私は2つの仕様で再利用したいキーワードClojureでマクロに渡す前にシンボルをその値に解決できますか?

(def keys [::description ::url ::mailing-list]) 

の次の配列を持っていると言います。 1つはマップを定義するためのもので、もう1つは関数へのオプションの引数を定義するためのものです。

(require '[clojure.spec :as spec]) 

(spec/def ::project-map 
     (spec/keys :opt-un keys)) 

(spec/def ::project-args 
     (spec/keys* :opt-un keys)) 

問題がkeyskeys* GETが引用されたシンボル'keysはなく、それが参照しています変数で開催された解決された値に合格したこと、その後です。

私の質問は、一般的なlisp #.リーダマクロのように読み取り時にキーの値を解決することは可能ですか、リストの代わりにシンボルを取得する場合は、マクロを再定義する必要がありますリテラル?

答えて

1

マクロは引数の評価方法を担当するため、別のマクロでラップすることもできます。

(defmacro def-both [name name* keys] 
    `(do (s/def ~name (s/keys :opt-un ~keys)) 
     (s/def ~name* (s/keys* :opt-un ~keys)))) 

(user/def-both ::project-map ::project-args [::description ::url ::mailing-list]) 
1

あなたはevalで半分不快なソリューションを構築することができますが:clojuriansのたるみにmpenedによって

(spec/def ::project-map 
    (eval `(spec/keys :opt-un ~keys))) 

(spec/def ::project-args 
    (eval `(spec/keys* :opt-un ~keys))) 

これが示唆されました。

+1

Clojureのとよく作品しかし、残念なことにclojurescriptではありません –

+1

うん、それは仕様がそんなに悲しいクロウヘビー。 – Rovanion

+0

さて、私は最後にマクロを使ってしまった。私はマクロでラップすることなく、その1つのシンボルを展開することができたらいいと思う。 –

0

それとも、単に行うことができます:

(spec/def ::project-map (spec/keys ::opt-un ~keys)) 

はqualitified名前空間(たとえば、::opt-un)を使用する必要があります

spec/def 

が既にマクロです;)

+0

これがなぜ機能するのか分かりません。 ':: opt-un'は':my-namespace/op-un'の短縮形であるため、 ':opt-un'よりも名前付きarg':opt-un'と一致してはいけません。失敗したアサーションを見ると、指定された引数の値が名前付き引数ではなく、修飾されたキーワードであるかどうかがチェックされます。 [編集]:それは動作しません。あなたが仕様から生成するときに得られるものを見てください。 ':: opt-un'は単に無視されるので、〜〜の内容はチェックされません。 – Rovanion

関連する問題