首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解Clojure中使用宏的符号解析

理解Clojure中使用宏的符号解析
EN

Stack Overflow用户
提问于 2022-10-26 13:06:25
回答 1查看 54关注 0票数 0

我正在学习clojure中的宏。我需要在宏中的符号解析帮助。

代码语言:javascript
复制
(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不能在第二种情况下解析全局变量,为什么它可以在第一个宏中解析全局变量?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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显式解析传递的符号(需要使用@来获取已解析的变量的值):

代码语言:javascript
复制
(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)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74208310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档