宏的示例代码 - 相同(种类)错误

时间:2013-09-23 02:49:33

标签: macros clojure

我已经阅读了来自的宏教程 http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-i-getting.html网站,我不明白如何调试一些错误。 有人可以描述错误/不正确吗?

  • 简易版
(defmacro dbgm_v1 [s] 
   (list 'let ['a s] (list 'println (list 'quote s) "=" 'a) 'a)
)
;;;;
(defn factorial_v1 [n] 
   (if (< n 2) n
        (dbgm_v1 (* n factorial_v1(dec n)) )
    ) 
)
;;

; let's test it
(factorial_v1 5) 
ClassCastException clojure.dg.alfa01$factorial_v1 cannot be cast to java.lang.Number  clojure.lang.Numbers.multiply (Numbers.java:146)
  • 复杂版本
(defmacro dbgm_v9 [x] 
  `(let  [x# ~x] (println '~x "=" x#) x#)
)
;
(defn factorial_v9 [n]
  (if (< n 2) n
    (dbgm_v9 (* n factorial_v9 (dec n)))
))
;
user=> (factorial_v9 5)
ClassCastException clojure.dg.alfa01$factorial_v9 cannot be cast to java.lang.Nu
mber  clojure.lang.Numbers.multiply (Numbers.java:146)
user=>

失败并出现同样的错误。

上述代码有什么问题? 提前感谢您提供任何提示/网址/笔记!

DG

1 个答案:

答案 0 :(得分:1)

您缺少左括号。

(defmacro dbgm_v9 [x] 
  `(let  [x# ~x] (println '~x "=" x#) x#))

(defn factorial_v9 [n]
  (if (< n 2) n
    (dbgm_v9 (* n (factorial_v9 (dec n))))))
                 ;^ Missing (
(factorial_v9 5) ;=> 120

您可以使用macroexpand验证宏的扩展方式。

(macroexpand '(dbgm_v9 (* n factorial_v9 (dec n))))
;=>
(let* [x__31341__auto__ (* n factorial_v9 (dec n))]
  (clojure.core/println (quote (* n factorial_v9 (dec n))) "=" x__31341__auto__)
  x__31341__auto__)

*尝试对nfactorial_v9(dec n)进行操作时,会导致异常。由于*对数字进行操作,因此它尝试将factorial_v9转换为数字并失败。