我正在为API服务器创建一个库,这里是我的简化版本:
(defonce ^:dynamic *my-token* nil)
(defmacro def-my-token
[token1 & body]
`(binding [*my-token* ~token1] ~@body))
主要的“帖子”方法:
(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"))))
但它说“无法在此上下文中解析符号:my-token”
我想知道为什么? dons't def-my-token,作为一个宏,定义它?为什么不?以及如何解决这个问题?
更新:
也没有(defonce ^:dynamic *token* nil)
它不起作用。为什么不?
为什么不足够定义宏?
答案 0 :(得分:3)
回答您的更新:
根据binding的文档,您只能覆盖已存在的变量。这就是为什么如果没有为动态var建立根绑定,你的解决方案就无法工作。
旁注:
我建议做jmargolisvt所说的并使用普通def
代替defonce
,因为我从未在野外使用defonce
看到任何动态var定义。
编辑:
dons't def-my-token,作为一个宏,定义它?为什么不?以及如何解决这个问题?
宏本身并没有定义东西,它们是在大多数Lisp REPL
的宏扩展步骤中转换源代码的小程序。它可以定义您想要的任何内容,但是您应该编写def
特殊表单。您使用的是binding
来处理已有的变量。
你可以通过在REPL中玩弄它和/或阅读这个stackoverflow answer的答案来获得更多的洞察力。
如果您需要进一步解释,为什么需要overriding
:
将vars概念化为堆栈是切实可行的。使用def
建立的根绑定是第一层。程序中的所有内容都会看到此值,除非您在其上添加“内容”。您可以想象,在您的函数中将*my-token*
视为nil
的示例会导致问题。
binding
到了resuce!
它允许你将根绑定(在你的情况下为nil
)中的任何东西置于主体内部的线程 - 就像这样:
答案 1 :(得分:2)
你绑定了*my-token*
,而不是my-token
。尝试:
{:body (json/write-str (:secret *my-token*))
星号只是动态变量的命名约定,它们仍然是实际var名称的一部分。