宏中的绑定未解析
a binding in a macro isn't resolved
我正在为 API 服务器创建一个库,这是我拥有的一个简化版本:
(defonce ^:dynamic *my-token* nil)
(defmacro def-my-token
[token1 & body]
`(binding [*my-token* ~token1] ~@body))
主要"post"方法:
(defn my-post-request [url1]
(try
(let [res (client/post (str "api/url/base" url1)
{:body (json/write-str (:secret my-token)) ; my-token should come from the macro
;......
下面是我想要使用它的方式:
(defn -main [& args]
(def-my-token "fdsfdsfdsfds"
; now "my-token" should be created and visible in "my-post-request", shouldn't it?
(print
(my-post-request "/some_end_point"))))
但是它说 "Unable to resolve symbol: my-token in this context"
我想知道为什么? def-my-token,作为一个宏,不定义它吗?为什么不?以及如何解决这个问题?
更新:
也没有 (defonce ^:dynamic *token* nil)
它不起作用。为什么不?
为什么宏定义不够?
你绑定了 *my-token*
,而不是 my-token
。尝试:
{:body (json/write-str (:secret *my-token*))
星号只是动态变量的命名约定,它们仍然是实际变量名称的一部分。
对您更新的回答:
根据 binding 的文档,您只能覆盖 已经存在的 变量。这就是为什么如果不建立与动态变量的根绑定,您的解决方案就无法工作的原因。
旁注:
我建议按照 jmargolisvt 所说的去做,并使用普通的 def
而不是 defonce
,因为我从未见过使用 defonce
的任何动态 var 定义。
编辑:
doens't def-my-token, being a macros, define it? why not? And how to fix that?
宏本身不定义任何东西,它们是在大多数 Lisp REPL
的 macro-expansion 步骤中转换源代码的小程序。它可以定义您想要的任何内容,但是您应该编写 def
特殊形式。您使用的是 binding
来处理已经存在的变量。
通过在 REPL and/or 阅读此 Whosebug answer.
的答案,您可能会获得更多见解
如果您需要进一步解释为什么需要 overriding
:
将 vars 概念化为堆栈是实用的。您使用 def
建立的根绑定是第一层。你程序中的所有东西都会看到这个值,除非你把 "something" 放在它上面。正如您可以想象的那样,在您的示例中 *my-token*
从您的函数中被视为 nil
会导致问题。
binding
求救!
它允许您将任何 "on top" 的根绑定(在您的情况下 nil
)thread-locally 放入它的正文中,如下所示:
我正在为 API 服务器创建一个库,这是我拥有的一个简化版本:
(defonce ^:dynamic *my-token* nil)
(defmacro def-my-token
[token1 & body]
`(binding [*my-token* ~token1] ~@body))
主要"post"方法:
(defn my-post-request [url1]
(try
(let [res (client/post (str "api/url/base" url1)
{:body (json/write-str (:secret my-token)) ; my-token should come from the macro
;......
下面是我想要使用它的方式:
(defn -main [& args]
(def-my-token "fdsfdsfdsfds"
; now "my-token" should be created and visible in "my-post-request", shouldn't it?
(print
(my-post-request "/some_end_point"))))
但是它说 "Unable to resolve symbol: my-token in this context"
我想知道为什么? def-my-token,作为一个宏,不定义它吗?为什么不?以及如何解决这个问题?
更新:
也没有 (defonce ^:dynamic *token* nil)
它不起作用。为什么不?
为什么宏定义不够?
你绑定了 *my-token*
,而不是 my-token
。尝试:
{:body (json/write-str (:secret *my-token*))
星号只是动态变量的命名约定,它们仍然是实际变量名称的一部分。
对您更新的回答:
根据 binding 的文档,您只能覆盖 已经存在的 变量。这就是为什么如果不建立与动态变量的根绑定,您的解决方案就无法工作的原因。
旁注:
我建议按照 jmargolisvt 所说的去做,并使用普通的 def
而不是 defonce
,因为我从未见过使用 defonce
的任何动态 var 定义。
编辑:
doens't def-my-token, being a macros, define it? why not? And how to fix that?
宏本身不定义任何东西,它们是在大多数 Lisp REPL
的 macro-expansion 步骤中转换源代码的小程序。它可以定义您想要的任何内容,但是您应该编写 def
特殊形式。您使用的是 binding
来处理已经存在的变量。
通过在 REPL and/or 阅读此 Whosebug answer.
如果您需要进一步解释为什么需要 overriding
:
将 vars 概念化为堆栈是实用的。您使用 def
建立的根绑定是第一层。你程序中的所有东西都会看到这个值,除非你把 "something" 放在它上面。正如您可以想象的那样,在您的示例中 *my-token*
从您的函数中被视为 nil
会导致问题。
binding
求救!
它允许您将任何 "on top" 的根绑定(在您的情况下 nil
)thread-locally 放入它的正文中,如下所示: