您可以将top-section 扩展为特制的let 表单,将link 符号绑定到原始link 函数与top-section 表单的第一个参数的部分应用:
(defmacro top-section [n s & forms]
`(let [~'link (partial ~'link ~n)]
(prn ~s) ; handle s in whichever way is appropriate
~@forms))
;; for the sake of example
(defn link [n s] (prn n s))
REPL 交互(打印三行,返回 nil):
user> (top-section 1 "start of text"
(link "more text")
(link "still more"))
"start of text"
1 "more text"
1 "still more"
nil
如果top-sections 可能需要嵌套,您可以使用更复杂的top-section,它会小心抓取“命名空间范围”link:
(defmacro top-section [n s & forms]
(let [qlink (symbol (name (.. (resolve 'link) ns name)) "link")]
`(let [~'link (partial ~qlink ~n)]
(prn ~s)
~@forms)))
在 REPL:
user> (top-section 1 "start of text"
(link "more text")
(link "still more")
(top-section 2 "inner section"
(link "etc.")))
"start of text"
1 "more text"
1 "still more"
"inner section"
2 "etc."
nil
(接下来是一个很可能完全不必要的复杂化——top-section 的可配置变体——如果没有用,希望它有点令人愉快......)
顺便说一句,您是否有一小部分固定的函数想要以这种方式处理,或者您认为它可能会扩展/变得很大?在后一种情况下,您可以让 top-section 对所有持有的符号执行相同的操作,例如在某处的 Atom 中:
(def top-section-syms (atom #{'link}))
(defmacro top-section [n s & forms]
(let [nsym (gensym "n")
qs (for [s @top-section-syms]
[s (symbol (name (.. (resolve s) ns name)) (name s))])]
`(let [~nsym ~n
~@(->> (for [[s q] qs]
[s `(partial ~q ~nsym)])
(apply concat))]
(prn ~s)
~@forms)))
在 REPL:
user> (swap! top-section-syms conj 'prn)
#{prn link}
user> (top-section 1 "start of text"
(link "more text")
(link "still more")
(top-section 2 "inner section"
(link "etc.")
(prn "and another fn...")))
"start of text"
1 "more text"
1 "still more"
"inner section"
2 "etc."
2 "and another fn..."
nil
swap!ing 在新符号中的操作可以通过一个简单的函数/宏 (register-top-section-symbol?) 来美化。