0

次のことを行うマクロを定義しようとしています。

  • 「変数」を初期値にバインドする
  • 変数名に基づいた名前で setter メソッドを作成する

clojure ファイルで次のように定義しています。

(defmacro defprop
  [prop-name init-value]
  `(do
    (def ~prop-name ~init-value)
    (def ~(symbol (str prop-name "-other")) ~init-value)
    (defn ~(symbol (str prop-name "-11")) [] (set! ~prop-name 11))
    (defn ~(symbol (str prop-name "-set")) [new-val] (set! ~prop-name new-val))))

次のように clojurescript から呼び出すと (cmacros は名前空間のエイリアスです):

(cmacros/defprop production 350)

「生産」と「生産-その他」の定義は正しく、機能「生産-11」は機能します(そして生産の値を11に設定します)が、最後のものは機能しません。さまざまなブラウザーでさまざまなエラーが発生します。Chrome で「Uncaught SyntaxError: Unexpected token .」と表示されます。Firefox "SyntaxError: 形式パラメーターの後に ) がありません"。

Firefox によって指摘された問題のある JavaScript コードは次のようになります。

cgamemini.core.production_set = (function
  cgamemini$core$production_set(cgamemini.macros.new_val) {
    return cgamemini.core.production = cgamemini.macros.new_val;
  }
);

私はjsの専門家ではありませんが、括弧はすべて正しいようです。何がうまくいかないのですか?-11 定義は機能するのに -set が機能しないのはなぜですか?

4

1 に答える 1

2

問題はnew-val. Clojure マクロ展開は構文を理解しないため、それがnew-val引数であると想定されていることを認識しません。マクロ展開で発生する裸のシンボルは、現在の名前空間に自動的に名前空間化されます。そのためcgamemini$core$production_set(cgamemini.macros.new_val)、出力に表示されます。あなたがしたいことは、名前空間化されていない新しいシンボルを作成する必要があることを示すために、衛生的なマクロ構文を使用することです。

`(defn ~(symbol (str prop-name "-set")) [new-val#] (set! ~prop-name new-val#))

別の方法は、シンボルを挿入することです。

`(defn ~(symbol (str prop-name "-set")) [~'new-val] (set! ~prop-name ~'new-val))
于 2015-08-03T02:18:18.527 に答える