Creating a hash-map with conditional keys

1,131 views
Skip to first unread message

Ryan

unread,
Feb 21, 2013, 9:50:00 AM2/21/13
to clo...@googlegroups.com
Hello,

I am trying to figure out how to make the following elegantly in clojure. 

I have a hash-map which has some key-value pairs and I would like to append to that hash-map a couple more key-value pairs IF some specific condition is met. For example, the create-map creates the main hash-map but i would like to merge the map with the value returned from create-key-value, if the condition inside that function is met.

(defn create-key-value [value] 
 (when (some-condition-true) {:extra-key "extra-value")) 
 
(defn create-map [] 
    {:foo "a"
     :bar "b"}) 

The final, merged, map should look like this if create-key-value returned the :extra-key

{:foo "a", :bar "b", :extra-key "extra-value"}

...or if it didn't to return this:
 
 {:foo "a", :bar "b"}

I did find a proposed solution on a stackoverflow post, but I am not sure if that's the most elegant way. 

Thank you for your time.

Regards,

Ryan

Meikel Brandmeyer (kotarak)

unread,
Feb 21, 2013, 10:02:21 AM2/21/13
to clo...@googlegroups.com
Hi,

merge works with nil. So (merge (create-map) (create-key-value "some-value")) should work as you intend with the functions as they are defined now.

Kind regards
Meikel

Ryan

unread,
Feb 21, 2013, 10:27:28 AM2/21/13
to clo...@googlegroups.com
Thanks Meikel for your reply.

It wasn't clear on my example, but I wish to use merge inside my create-map function. Do you think I should bind my hash-map to a let variable first and then apply merge, or do you have another proposal? What i mean is this:

(defn create-key-value [value] 
 (when (some-condition-true) {:extra-key value)) 

(defn create-map [] 
  (let [my-map {:foo "a" :bar "b"}]
    (merge my-map (create-key-value "some-value")))

Is the above "clojurish" or is there a better way? For example if the my-map was a big hash-map, and not with just two pairs, wouldn't it be ugly with the above way? or..it's just fine and no better way is possible?

Ryan 

Alex Baranosky

unread,
Feb 21, 2013, 10:41:49 AM2/21/13
to clo...@googlegroups.com
I'd often just write it like this:

(defn create-map []
  (merge {:foo "a"
               :bar "b"
               ... many more keys}
              (when (some-condition-true)
                 {:extra-key value)))

Alex

--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Alex Baranosky

unread,
Feb 21, 2013, 10:46:18 AM2/21/13
to clo...@googlegroups.com
Another alternative way, added in Clojure 1.5, can be nice if you have a lot of conditionally-added key-value pairs:

(defn create-map []
  (cond-> {:base :map}
          (pred1) (assoc :extra-key1 value)
          (pred2) (assoc :extra-key2 value)
          (pred3) (assoc :extra-key3 value)
          (pred4) (assoc :extra-key4 value)))

Ryan

unread,
Feb 21, 2013, 10:53:18 AM2/21/13
to clo...@googlegroups.com
Thanks for your input Alex.

Do you think a macro would be appropriate if I use this more than once in my code?

Ryan

Alex Baranosky

unread,
Feb 21, 2013, 12:05:11 PM2/21/13
to clo...@googlegroups.com

A function could be appropriate, but a macro  not appropriate, since everything you need here can be done with using macros.

Ryan

unread,
Feb 21, 2013, 12:11:12 PM2/21/13
to clo...@googlegroups.com
I got confused a bit with the reason that a macro would not be appropriate for this case. Can you please explain again?

Ryan

Alex Baranosky

unread,
Feb 21, 2013, 12:41:12 PM2/21/13
to clo...@googlegroups.com
Macros should be avoided if you don't need them.  Otherwise they drastically reduce code readability.  In this case you just have some predicates and maps that need to be combined conditionally, so nothing macros do is needed.  The real question here is why you would need a macro?  Macros usage is, to me, a question of need, meaning I need to convince myself that you need it or I wouldn't sacrifice code readability for it.

Things macros are good for: 
  • delayed code evaluation
  • DSL creation
  • moving computation to compile time (comes up occasionally)
  • other metaprogramming, which I usually only consider worth it if it reduces duplication enough
Alex

Jim - FooBar();

unread,
Feb 21, 2013, 12:43:05 PM2/21/13
to clo...@googlegroups.com
I think Alex is trying to say that a macro is almost never appropriate when a first-class function would do...therefore, there is no good reason for carrying the complexity of macros all over your code, given that in your case they do nothing special (like postponed evaluation) and can be replaced by functions.

Jim

Ryan

unread,
Feb 21, 2013, 12:44:37 PM2/21/13
to clo...@googlegroups.com
Thank you both for your answers

Regards,

Ryan
Reply all
Reply to author
Forward
0 new messages