我正在尝试编写一个将地图作为输入的宏,并引用该地图中存在的每个符号(键和值)。
这是我想做的。假设我有一个宏quote-everything
,它将这样的地图作为输入:
{foo "foo" :bar bar}
然后,评估:
(quote-everything {foo "foo" :bar bar})
会产生:
{quote(foo) "foo" :bar quote(bar)}
基本上,我希望宏生成一个新的地图,其中引用了每个符号。问题是我不知道从哪里开始,如果有可能的话。问题是地图可以是任何东西,宏也应该支持嵌套地图。
可以使用symbol?
完成符号的检测。但是,为了支持嵌套映射,宏可能应该调用自己。但是我不知道应该用这样的宏创建新地图。
任何指针都会受到赞赏。
答案 0 :(得分:5)
quote
特殊表单已为您完成此操作:
user> (= (quote {foo "foo" :bar bar})
{(quote foo) "foo" :bar (quote bar)})
;; => true
所有引用都会阻止评估表单。我想你可能会比实际需要更难。
答案 1 :(得分:2)
clojure.walk/postwalk
可能会对您有所帮助:
(require '[clojure.walk :as w])
(w/postwalk
(fn [x]
(if (symbol? x)
`(quote ~x)
x))
'{foo :foo :bar bar})
;; => {(quote foo) :foo, :bar (quote bar)}
将其包裹在defmacro
中,它应该让你开始。请注意,这确实引用了每个符号,因此如果您有(inc 1)
之类的内容,则最终会显示为((quote inc) 1)
。这可能实际上就是你想要的,我只是想我会提到它。