2017-12-01 5 views
0

私はそれを行う関数への呼び出しをリダイレクトするマクロを書こうとしています。公開されたすべての関数を最上位のcljファイルに集める方法です。 https://martinfowler.com/bliki/PublishedInterface.htmlコピー:arglists in clojure def

私はdoc文字列とarglistsをコピーしたいですが、docstringはうまく動作しますが、argsリストはコピーされません。私は何が欠けていますか?

(defmacro idef 
    [fname] 
    (let [sym (symbol (str "clojure.core/" fname)) 
     metas (meta (find-var sym)) 
     arglists (:arglists metas) 
     doc (:doc metas)] 
    ;;`(def ~(with-meta fname {:doc doc :arglists arglists})) 
    `(def ~(with-meta fname {:doc doc}) 
     ~sym))) 

(idef inc) 

私が代わりにコメント行を使用している場合、私は、これは名前空間はClojureのコアにハードコードされただけのサンプルです

CompilerException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector, compiling:(interface.clj:22:1) 

を取得します。

この質問は本当に似ていますが、私はコピーは問題ありませんを参照してください。ドキュメントの一部を、特別な程度にするものです。arglists

Help me write a Clojure macro which automatically adds metadata to a function definition

答えて

0

arglistsは基本的にリストされているので、あなたがそのエラーを取得しています~でスプライスすると、このリストが評価されます。

は私の例で説明しましょう:

user> (:arglists (meta #'clojure.core/inc)) 
([x]) 

あなたは、マクロ内~(with-meta fname {:doc doc :arglists arglists})をしようとあなたがarglistsシンボルにバインドされている文字通り評価する形態です。だから、incの場合、あなたは、本質的にこれを実行しようとしている:あなたが取得しているエラーを報告

user> ([x]) 
ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity (AFn.java:429) 

を。

これを避けるには、arglistsフォームが評価されないようにする必要があります。これを達成する方法の1つは、quoteコール以内にそれを置くことです:

(defmacro idef 
    [fname] 
    (let [sym (symbol (str "clojure.core/" fname)) 
     metas (meta (find-var sym)) 
     arglists (:arglists metas) 
     doc (:doc metas)] 
    `(def ~(with-meta fname {:doc doc :arglists `(quote ~arglists)}) ~sym))) 
+0

はそのような何かをしようとしましたが、私はバッククォート内部のバッククォートを持つことができます実現しませんでした。ありがとう! – mattias

関連する問題