2014-06-16 49 views
0

我正在尝试编写一个将地图作为输入的宏,并且会引用该地图中存在的每个符号(键值为&值)。Clojure:创建一个宏来引用地图的每个符号

这是我想要做的。比方说,我有一个宏观quote-everything是拿一张地图这样的输入:

{foo "foo" :bar bar} 

然后,评估:

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

将产生:

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

基本上,我想宏观生成引用每个符号的新地图。问题是我不知道从哪里开始,甚至可能。事情是,地图可以是任何东西,并且宏也应该支持嵌套地图

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

任何指针,将不胜感激。

+2

刚才在顶层引用地图时出现了什么问题?那不符合你的需求? – Alex

回答

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

+0

太棒了,这正是我正在寻找的(人行道)。从那里,我将能够调整它,我需要做的,谢谢! – Neoasimov

5

quote特殊形式已经这样做了你:

user> (= (quote {foo "foo" :bar bar}) 
     {(quote foo) "foo" :bar (quote bar)}) 
;; => true 

所有报价确实是防止形式从被评估。我认为你可能会让它比需要的更难。

+0

这真的很好知道!实际上,我可能应该指定我的问题是关于如何使用postwalk来修改地图并返回修改的地图而不是'quote'本身。无论如何,这是很好的了解,“报价”就是这样工作的。 – Neoasimov

相关问题