hash-map initialization issue

135 views
Skip to first unread message

Ryan

unread,
Mar 28, 2013, 5:16:39 PM3/28/13
to clo...@googlegroups.com
Hello!

I am having a small issue with a hash-map initialization and I am failing to understand why. I have the following situation:

(def a-list '({:BAR_KEY bar-value}, {:BAR_KEY another-value}))

(defn my-function [foo-id a-keyword a-list] 
  (map #({:foo_id foo-id (keyword a-keyword) (:BAR_KEY %)}) a-list))

So, by running the above function like this:

(my-function 5 "my_keyword" a-list) 

I get the following error:

clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentArrayMap
 
I am trying to get the following result:

({:foo_id 5 :my_keyword bar-value}, {:foo_id 5 :my_keyword another-value})

Any ideas? I have played around in repl for the last 2 hrs but I haven't found the proper way to do this.

Thank you for your time :)

Jonathan Fischer Friberg

unread,
Mar 28, 2013, 5:24:38 PM3/28/13
to clo...@googlegroups.com
It's because the #() syntax always calls the content as a function.

So #(...) is the same as (fn [] (...)). In your case,
#({:foo_id foo-id (keyword a-keyword) (:BAR_KEY %)})
is the same as:
(fn [%] (
{:foo_id foo-id (keyword a-keyword) (:BAR_KEY %)}))
Note the extra () around {}. In other words, your map is called
as a function.

Maps can normally be called as functions, like this:
({:hello :world} :hello)
=> :world
That's why you get the "Wrong number of args" error
(and not a "a map is not a function" error).
Hope that makes sense.

Btw, hyphen is normally used instead of underscore
in both variables and keywords. Just a slight style
"issue", but maybe you had your reasons. :)

Jonathan


--
--
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.
 
 

Ryan

unread,
Mar 28, 2013, 5:51:10 PM3/28/13
to clo...@googlegroups.com
Thanks for your explanation Jonathan. I am still a bit confused however what is the proper solution here. Should i use an anonymous function instead to do what I want or can it be done with the #() syntax?

Hyphens is my preferred way as well, but, those keys represent sql columns which they use underscore so I gotta go with underscores in order code to match them :)

Ryan

Jonathan Fischer Friberg

unread,
Mar 28, 2013, 6:08:04 PM3/28/13
to clo...@googlegroups.com
It can still be done with the #(), with for example the hash-map function.
It's basically the same as the {} but as a function, like this:
(hash-map :a 3 :b 4)
=> {:a 3, :b 4}

So you should be able to write the function as:
#(hash-map :foo_id foo-id (keyword a-keyword) (:BAR_KEY %))

I think you should use the standard (fn []) syntax though, since it's shorter.


> Hyphens is my preferred way as well, but, those keys represent sql columns which they use underscore so I gotta go with underscores in order code to match them :)
I see. :)

Jonathan

Ryan

unread,
Mar 28, 2013, 6:19:05 PM3/28/13
to clo...@googlegroups.com
Thanks for all your help Jonathan :) I went with the standard fn syntax, its a two-liner anyway so not a big of deal :)
The important part here was that I learned that #() executes the content as a function, very helpful!

Ryan

Jonathan Fischer Friberg

unread,
Mar 28, 2013, 6:26:24 PM3/28/13
to clo...@googlegroups.com
No problem, glad to be of help. :)

Jonathan

JvJ

unread,
Mar 30, 2013, 11:58:31 PM3/30/13
to clo...@googlegroups.com
Here's a cheezy hack, use identity.

#(identity {:foo %})

JvJ

unread,
Mar 31, 2013, 3:57:51 AM3/31/13
to clo...@googlegroups.com
...even cheezier, use do
#(do {:foo %})

Alex Baranosky

unread,
Mar 31, 2013, 4:11:08 AM3/31/13
to clo...@googlegroups.com
There's also 'for'

(defn my-function [foo-id a-keyword a-list]  
  (for [m a-list]
    {:foo_id foo-id (keyword a-keyword) (:BAR_KEY m)})) 

Ryan

unread,
Apr 1, 2013, 1:12:51 AM4/1/13
to clo...@googlegroups.com
Thanks for your input guys

Ryan

Gary Verhaegen

unread,
Apr 2, 2013, 9:15:58 AM4/2/13
to clo...@googlegroups.com
And there's the threading macro : #(-> {:foo %})

Ryan T.

unread,
Apr 2, 2013, 2:57:44 PM4/2/13
to clo...@googlegroups.com
Thanks Gary, it didn't cross my mind that i can use the # reader with the threading macro :)


You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/SreXPqbyjJ0/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.

Ryan

unread,
Apr 2, 2013, 2:58:18 PM4/2/13
to clo...@googlegroups.com
Thanks Gary, it didn't cross my mind that i can use the # reader with the threading macro :)

Michał Marczyk

unread,
Apr 2, 2013, 5:36:05 PM4/2/13
to clo...@googlegroups.com
On 28 March 2013 22:51, Ryan <areka...@gmail.com> wrote:
> Thanks for your explanation Jonathan. I am still a bit confused however what
> is the proper solution here. Should i use an anonymous function instead to
> do what I want or can it be done with the #() syntax?

Just wanted to add that the #() syntax is just shorthand notation
expanded by the reader into fn* forms, so what it produces is an
anonymous function, with no special magic. To see the exact expansion,
you can quote a #() form:

user=> '#(foo)
(fn* [] (foo))

fn* is the special form behind #() and fn (which is a macro);
basically an implementation detail.

Cheers,
Michał
Reply all
Reply to author
Forward
0 new messages