Clojure宏参数

时间:2013-01-18 12:15:24

标签: macros clojure

大约一周前,我在这个帖子中提出了一个问题:Looping through a "let"-list in Clojure? 然而,我得到了一个很好的答案,我脑子里出现了一个相当令人困惑的问题:

以下是答案的一部分:

(defmacro anaphoric-let [alternating-symbols-and-values & body]
    `(let [~@alternating-symbols-and-values
           names# (quote ~(flatten (partition 1 2 alternating-symbols-and-values)))
           values#  ~(vec (flatten (partition 1 2 alternating-symbols-and-values)))
           ~'locals (zipmap names# values#)]
        ~@body))


Input: 
(anaphoric-let [a 1 b 2 c 3 d 4 e "cat"] 
     (dorun (for [x (vals locals)] 
          (if (number? x) (println "roar")))))

这种情况下的(dorun)语句是宏参数中的正文吗?因此我觉得它只是“复制粘贴”身体。所以而不是:

~@body

它看起来像下面那样它将取消引用复制的文本和所有:

~@(dorun (for [x (vals locals)] 
       (if (number? x) (println "roar"))))

在我尝试解释发生的所有事情的过程中,我尝试了我刚刚解释的确切事情。而不是〜@ body我试图在那里放一些“真正的代码”。

它看起来像这样:

(defmacro anaphoric-let [alternating-symbols-and-values & body]
     `(let [~@alternating-symbols-and-values
          names# (quote ~(flatten (partition 1 2 alternating-symbols-and-values)))
          values#  ~(vec (flatten (partition 1 2 alternating-symbols-and-values)))
          ~'locals (zipmap names# values#)]
       ~@(dorun (for [x (vals locals)] 
             if (number? x) (println "roar"))))))

这不起作用并且抱怨它“无法解析符号:在此上下文中的本地人” 我是这样的新手,我试过试验和分析,但我没有明智。每当我想到这一切都弄明白的时候,总会有这个小小的“但是......”随之而来并且压垮了一切!

我觉得我对这个例子的其他部分有一个不错的理解,除了邪恶的〜@身体......我的个人猜测是因为我对如何结合所有这些小古怪缺乏充分的理解符号,我可能错过了某种组合......

1 个答案:

答案 0 :(得分:1)

反引号表达式中的

〜@ expr意味着评估expr并将其拼接到周围的表达式中

由于想要评估您的(dorun ...)表达式,您只需复制&粘贴它:

(defmacro anaphoric-let [alternating-symbols-and-values & body]
     `(let [~@alternating-symbols-and-values
          names# (quote ~(flatten (partition 1 2 alternating-symbols-and-values)))
          values#  ~(vec (flatten (partition 1 2 alternating-symbols-and-values)))
          locals# (zipmap names# values#)]
       (dorun (for [x (vals locals#)] 
           if (number? x) (println "roar"))))))

由于您不再需要将特定符号插入到正文中,我将替换的本地符号移动到gensym'd符号

现在为什么你想要在这样的硬编码宏中引入用户指定的符号,我不知道。我假设这只是为了实验。