tags:

views:

124

answers:

4

Title says it all,

here's the code :

(def entry {:name tempName :num tempNum})

(def tempList '(entry))

(println (get (nth tempList 0) (:name)))

Exception in thread "main" java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :name

In this bit of code, I define a map called entry containing a :name and a :num, then I put it in a list, then I try to print the :name field of the first (and only) element of the list. (or at least this is what I think my code does :o)

I can access name from the entry map before I put it in the list, but once it's in the list I get this error. What args am I supposed to give ?

+3  A: 

There are two problems.

First, for lists that contain symbols to be resolved (like the symbol entry in your case), you have to use syntax-quote (backtick) instead of regular quote (apostrophe); so this line:

(def tempList '(entry))

should be:

(def tempList `(entry))

or just (using a vector, which is more idiomatic and easier to use in Clojure):

(def tempList [entry]) ; no quoting needed for vectors

Then, change this line

(println (get (nth tempList 0) (:name)))

to either this:

(println (get (nth tempList 0) :name))

or this:

(println (:name (nth tempList 0)))
pmf
A: 

take the ( ) off from (:name) on the 3rd line. :keywords are functions that take a map as an argument and "look themselves up" which is quite handy though it makes the error slightly more confusing in this case

(get (nth '({:name "asdf"}) 0) :name))
Arthur Ulfeldt
+1  A: 

Using nth on a list is a bad idea because it has to do a linear search to retrieve your element, every time. Vectors are the right collection type to use here.

Vectors are "maps" of indices to values. If you use a vector instead of a list you can do this:

(:name (tempList 0))

Or:

(get (get tempList 0) :name)

Or:

(get-in tempList [0 :name]))
Brian Carper
A: 

I would write your code like this:

(def entry {:name tempName :num tempNum})

(def tempList (list entry))

(println (:name (first tempList)))

Note that first is much neater than using nth, and keywords can act as functions to look themselves up in the map. Another equivalent approach is to compose the functions and apply them to the list:

((comp println :name first) tempList)
Rich