具有功能定义的宏包括设置!不在Clojurescript

时间:2015-08-02 22:20:52

标签: macros clojurescript defn

我正在尝试定义一个应该执行以下操作的宏:

  • 用初始值绑定'变量'
  • 使用基于变量名称
  • 的名称创建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:missing”之后的形式参数“。

Firefox指出的违规JavaScript代码如下所示:

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

似乎所有的括号都是正确的,尽管我不是专家。 出了什么问题?为什么-11定义有效但不是-set?

1 个答案:

答案 0 :(得分: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))