4

我正在尝试从 html 内容构建一个快速目录。(为了缩短)

代码非常简单:

(defn toc [content]
 (doseq [i (take 5 (iterate inc 1))] 
   (let [h  (str "h" i)]
    (println ($ content h)))))

其中content是 html 内容,$clojure-soup所需的宏

尽管

($ content "h1")

工作,并返回所有标签的列表。

简单的:

($ content (str "h" 1))

就是不管我做什么都不会成功。

我该如何强制

(str "h" 1) 

在调用宏 之前正确评估?

解释原因的奖励积分:)

4

2 回答 2

3

如果正如您所暗示的那样,这是一个宏,这是不可能$的:这根本不是宏的工作方式。宏需要在编译时扩展成某种东西,而且它只能这样做一次。您有运行时数据,例如 的各种值h,但无法在编译时使用它。对我来说,这听起来$应该是一个功能。

于 2012-10-20T02:57:03.853 回答
2

Amalloy 回答问题why部分。对于making it work部分您将需要使用eval.

代替($ content h)使用

(eval `($ content ~h))

为什么会这样的另一种解释是基于宏在编译时执行什么操作以及它在运行时执行什么(即它发出什么代码)这一事实。下面是一个清除事情的例子。

(def user "ankur")
(defmacro do-at-compile [v] (if (string? v) `true `false))
(defmacro do-at-runtime [v] `(if (string? ~v) true false))

(do-at-compile "hello") ;; => true
(do-at-compile user) ;; => false, because macro does perform the check at compile time
(do-at-runtime "hello") ;; => true
(do-at-runtime user) ;; => true

宏在编译时$对传递的第二个参数进行计算,因此它在您的特定情况下不起作用。

于 2012-10-20T07:16:25.473 回答