我正在学习clojure中的宏。我需要在宏中的符号解析帮助。
(ns macros.testing)
(def no (rand-int 10))
(defmacro drawer []
`(do
~@(for [i (range no)]
`(print ~i))))
(drawer) ;; This can resolve the global variable `no` properly
(defmacro drawer-2 [n]
`(do
~@(for [i (range n)]
`(print ~i))))
(drawer-2 10) ;; This works fine too
(drawer-2 n) ;; This is not working, I'm unable to pass the global variable as an argument to the macro, although it's visible in the other case错误消息是class clojure.lang.Symbol cannot be cast to class java.lang.Number (clojure.lang.Symbol is in unnamed module of loader 'app'; java.lang.Number is in module java.base of loader 'bootstrap')。
为什么clojure不能在第二种情况下解析全局变量,为什么它可以在第一个宏中解析全局变量?
发布于 2022-10-26 13:30:52
当一个宏被计算时,它的参数被传递为“原样”,没有符号解析,就好像它们都被引用了一样。因此,如果您传递n,在宏中它将是一个符号n,而不是包含在相关变量中的值。如果你通过(inc 10),它将是'(inc 10)。诸若此类。
因此,在drawer中,(range no)之所以工作,是因为no引用了绑定到(rand-int 10)结果的var。
在drawer-2中,参数n在宏计算期间的值为(symbol "n") (或仅为'n)。而(range 'n)不能工作--这正是你所看到的“不能将一个符号转换成一个数字”的例外。
要解决这个问题,可以使用resolve显式解析传递的符号(需要使用@来获取已解析的变量的值):
(def value 10)
(defmacro drawer-2 [n]
(let [n (if (symbol? n)
@(resolve n)
n)]
`(do
~@(for [i (range n)]
`(print ~i)))))
(drawer-2 value)https://stackoverflow.com/questions/74208310
复制相似问题