宏中的绑定未得到解决

时间:2016-01-12 03:24:04

标签: clojure macros

我正在为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)它不起作用。为什么不? 为什么不足够定义宏?

2 个答案:

答案 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)中的任何东西置于主体内部的线程 - 就像这样:

vars

答案 1 :(得分:2)

你绑定了*my-token*,而不是my-token。尝试:

{:body (json/write-str (:secret *my-token*))

星号只是动态变量的命名约定,它们仍然是实际var名称的一部分。