Clojure:创建一个宏来引用地图的每个符号

时间:2014-06-16 17:57:06

标签: macros clojure

我正在尝试编写一个将地图作为输入的宏,并引用该地图中存在的每个符号(键和值)。

这是我想做的。假设我有一个宏quote-everything,它将这样的地图作为输入:

{foo "foo" :bar bar}

然后,评估:

(quote-everything {foo "foo" :bar bar})

会产生:

{quote(foo) "foo" :bar quote(bar)}

基本上,我希望宏生成一个新的地图,其中引用了每个符号。问题是我不知道从哪里开始,如果有可能的话。问题是地图可以是任何东西,宏也应该支持嵌套地图

可以使用symbol?完成符号的检测。但是,为了支持嵌套映射,宏可能应该调用自己。但是我不知道应该用这样的宏创建新地图。

任何指针都会受到赞赏。

2 个答案:

答案 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)。这可能实际上就是你想要的,我只是想我会提到它。