Reputation: 1174
I have a map like so:
{:a "some" :b (str :a " stuff")}
What I'm trying to do is to have the :b value of the map be "some stuff", but the above example doesn't work. I tried wrapping it in def;
(def foo {:a "some" :b (str (:a foo) " stuff")})
But that doesn't work either. How do I make this work?
Upvotes: 0
Views: 144
Reputation: 17849
also, you can employ macros for this case (for fun and education). Like you can make up simple anaphoric macro to do the trick:
(defmacro make-map-ana [& keyvals]
`(-> {}
~@(map (fn [[k v]] `((fn [~'it] (assoc ~'it ~k ~v))))
(partition-all 2 keyvals))))
that is how you use it:
user> (make-map-ana :a "some"
:b (str (:a it) " stuff"))
;;=> {:a "some", :b "some stuff"}
that gets expanded to clojure code this way:
(-> {}
((fn [it] (assoc it :a "some")))
((fn [it] (assoc it :b (str (:a it) " stuff")))))
so it gets reflective, passing the context (namely it
) downstream.
(make-map-ana :a :fun
:b it
:c it)
;;=> {:a :fun, :b {:a :fun}, :c {:a :fun, :b {:a :fun}}}
another way to write this macro, is to use the overriding in let
bindings:
(defmacro make-map-ana [& keyvals]
`(let [~'it {}
~@(mapcat (fn [[k v]] ['it `(assoc ~'it ~k ~v)])
(partition-all 2 keyvals))]
~'it))
now (make-map-ana :a "some" :b (str (:a it) " stuff"))
would expand into this:
(let [it {}
it (assoc it :a "some")
it (assoc it :b (str (:a it) " stuff"))]
it)
also producing the result you need
Upvotes: 1
Reputation: 95
Well, as cfrick said, I don't think you can access a map while you are building it like you wrote in your second example.
You could build a simple function like the one bellow.
(defn merge-a-b [map] (assoc map :b (str (:a map) (:b map))))
It's also useful if you end with a vector of those maps, like:
(def x2 [{:a "some", :b " stuff"} {:a "some-other", :b " stuff"}])
You can just use the map build-in in Clojure and run it like:
(map merge-a-b x2)
({:a "some", :b "some:a stuff"} {:a "some-other", :b "some-other stuff"})
Upvotes: 0
Reputation: 37073
You have to use a let
here (either define the map or the value of a). You can not access the map while it is build up.
Upvotes: 2