Clojure 集合、let、宏、螺母
我正在尝试从html内容构建一个快速的toc。(简而言之) 代码非常简单:Clojure 集合、let、宏、螺母,clojure,macros,Clojure,Macros,我正在尝试从html内容构建一个快速的toc。(简而言之) 代码非常简单: (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))
(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)
要在调用宏之前正确评估
解释原因的额外要点:)如果正如您所暗示的那样,
$
是一个宏,那么这是不可能的:这根本不是宏的工作方式。宏需要在编译时扩展成某些内容,并且只能扩展一次。您有运行时数据,如h
的各种值,但在编译时无法使用这些数据。对我来说,这听起来像是$
应该是一个函数。Amalloy回答问题为什么部分。对于使其工作
零件,您需要使用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
$
宏正在编译时对传递的第二个参数进行计算,因此它在您的特定情况下不起作用。嘿,Nicolas,完全无关,但仅供参考(取5(迭代inc 1))
可以替换为(范围16)