2012-09-25 3 views
5

これはTreat Clojure macro as a functionで議論されている問題と似ていますが、一番上の答えにアプローチしようとするとエラーが発生します。それは非常に複雑ですが、ここで私が何をしようとしたかの蒸留バージョンですので、うまくいけば、私の特定のアプリケーションについてはあまり情報は、必要ありません。関数としてのClojureマクロ/マクロの 'Partial'?

(defmacro make-fn [m arg1] 
    `(fn [& args#] 
     (eval `(~'~m ~'~arg1 [email protected]#)))) 

私はこのコンテキストでマクロを使用:

(let [columns (make-columns table-width) 
     table-name (keyword (str "table_" n))] 
    (apply (make-fn helpers/tbl table-name) columns)) 

"helpers/tbl"は、テーブル名キーワードと、列指定を含む可変数のリスト([:varchar 100]など)を必要とするマクロです。私はいくつかのテストを容易にするために、即座にランダムなデータベーステーブル仕様を作成しようとしています。マクロ展開はコンパイル時に行われ、私は中にランタイム値を含めるようにしようとしています:私は、ソートの問題を把握

CompilerException java.lang.RuntimeException: Unable to resolve symbol: table-name in this context, compiling:(NO_SOURCE_PATH:1) 

:上記のコードを実行しようとしたときとにかく、私は次のエラーを取得しますマクロの展開では、すべてを正しく設定するためにクォートとクォートを使用するのは奇妙な使い方です。私は基本的にはマクロの部分的な使い方が必要です。このメカニズムを異なる名前空間の異なるマクロに再利用できるようにする必要があります。また、すべての可変解像度が正しく機能するようにする必要があります。これも可能ですか?

答えて

2

この問題は、Clojureが構文引用符(バックティック)式内のシンボルを解決する方法によって発生します。意図しない変数の取り込みを避けるために、Clojureは、構文引用符式内のシンボルを常にVars(ではなく、のローカル)を参照するものとして解釈します。

これを回避するには、構文見積もりによって生成されたものと同等のフォーム構築コードを "独自の"ものにすることができます。 ...ところで

+0

(defmacro make-fn [m arg1] (let [g (gensym)] (list 'fn ['& g] (list 'eval (list 'concat (list 'list m arg1) g))))) 

うわー、これは私のCommon Lispの日にフラッシュバックのようなものです:それは罪のように醜いですが、それはちょうど私があなたを警告していなかったなんて言わないで...働きます、 'syntax-quote'に関する興味深い事実です:それは読者の中で完全に実装されています。読者がバックティックを見ると、次のフォームが読み込まれ、 'seq'、' concat'、および 'list'を使って再帰的に変換されます。コンパイラは結果として得られる 'concat' /' list'コードだけを見ます。 –

関連する問題