Neoasimov
Neoasimov

Reputation: 1111

Clojure: creating a macro to quote every symbols of a map

I am trying to write a macro that takes a map as input, and that will quote every symbol that exists in that map (keys & values).

Here is what I would like to do. Let's say I have a macro quote-everything that take a map like this as input:

{foo "foo" :bar bar}

Then, evaluating:

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

Would produce:

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

Basically, I want the macro to generate a new map where every symbols are quoted. The problem is that I am don't know where to start, and if it is even possible. The thing is that the map can be anything, and the macro should support nested maps as well.

The detection of the symbols could be done using symbol?. However, to support nested maps the macro should probably call itself. But I have no idea how the new map should be created with such a macro.

Any pointers would be appreciated.

Upvotes: 0

Views: 189

Answers (2)

Alex
Alex

Reputation: 13941

The quote special form already does this for you:

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

All quotation does is prevents a form from being evaluated. I think you might be making this harder than it needs to be.

Upvotes: 5

xsc
xsc

Reputation: 6073

clojure.walk/postwalk might help you here:

(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)}

Wrap that in a defmacro and it should get you started. Note that that really quotes every symbol, so if you have something like (inc 1) in there it will end up as ((quote inc) 1). That might actually be what you want, I just thought I'd mention it.

Upvotes: 2

Related Questions