Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing a map inside a list in Clojure

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 ?

like image 872
JoOb Avatar asked Jul 18 '26 23:07

JoOb


2 Answers

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)))
like image 173
pmf Avatar answered Jul 21 '26 06:07

pmf


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]))
like image 20
Brian Carper Avatar answered Jul 21 '26 06:07

Brian Carper