1

大约一周前,我在这个帖子中问了一个问题:在 Clojure 中循环遍历“let”列表? 我得到了一个很好的答案,然而,一个相当令人困惑的问题出现在我的脑海中:

以下是部分答案:

(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"))))))

这不起作用并抱怨它是“无法解析符号:在这种情况下的本地人”我是一个新手,我已经尝试过实验和分析,但我并没有变得更聪明。每次我想我都明白了,总会有一个小小的“但是……”出现并粉碎一切!

我觉得我对示例的其余部分确实有一个不错的理解,除了邪恶的 ~@body ... 我个人的猜测是,由于我对如何组合所有这些古怪的小符号缺乏全面的了解,所以我可能错过了它们的某种组合......

4

1 回答 1

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 符号

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

于 2013-01-18T12:39:32.920 回答