【问题标题】:recursive macro arityexception递归宏arityexception
【发布时间】:2014-04-01 04:48:03
【问题描述】:

我正在尝试编写一个与线程宏在功能上相似(我认为)的宏,但是这将允许我指定一个关键字,其中前一个表单的插入将发生。我正计划使用 clojure.walk/prewalk-replace,但我得到了一个 clojure.lang.ArityException。这是代码:

(defmacro streamops [data form]
  (let [keewurd :...]
    (cond
      (not (seq? form)) form
      (= (count form) 0) data
      :else (streamops ~(clojure.walk/prewalk-replace
                          {keewurd data} (first form))
                       ~(rest form)))))`

但是当我尝试应用单元测试时:

(= (macroexpand '(streamops 3 ( (+ 1 :...) (* :... 2))))
   '(* (+ 1 3) 2))

它产生:

clojure.lang.ArityException: Wrong number of args (-1) passed to: walk$prewalk-replace
       Compiler.java:6473 clojure.lang.Compiler.macroexpand1
            core.clj:3633 clojure.core/macroexpand-1
            core.clj:3642 clojure.core/macroexpand

我做错了什么?

【问题讨论】:

  • 另一方面,看看swiss-arrows,有一个宏可以完成您想要完成的工作。

标签: macros clojure arity


【解决方案1】:

您的宏定义中似乎有一个错误的语法引用 `,因为它位于您发布的代码的末尾,但在您使用 unquote 的形式中没有语法引用~.

以下工作正常:

(defmacro streamops [data form]
  (let [keewurd :...]
    (cond
      (not (seq? form)) form
      (= (count form) 0) data
      :else `(streamops ~(clojure.walk/prewalk-replace
                          {keewurd data} (first form))
                       ~(rest form)))))

(= (macroexpand '(streamops 3 ( (+ 1 :...) (* :... 2))))
   '(* (+ 1 3) 2))

;= true

【讨论】:

  • 第一次宏展开后,代码是否重新评估宏展开?这似乎返回了一个包含宏的表单,然后不会对其进行评估,因为它是作为常规代码返回的。
  • 是的,代码被重新评估,macroexpand 的结果返回(* (+ 1 3) 2)。此外,使用macroexpand-1 会返回(user/streamops (+ 1 3) ((* :... 2))),正如预期的那样。
猜你喜欢
  • 2019-03-31
  • 2020-05-25
  • 1970-01-01
  • 1970-01-01
  • 2014-06-17
  • 2013-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多