0
votes

I am new clojure and am not able to understand exact issue while running this code

(def my-map {name "Srini" empid "10000"})

Receving this error:

CompilerException java.lang.RuntimeException: Unable to resolve symbol: empid in this context, compiling:(/Users/srini/Downloads/clojureexample/my-stugg/src/my_stugg/corecomponents.clj:95:1)

(def my-map {name "Srini" :empid "10000"})

Running successfully.

What wrong I am doing in the first line?

(def my-map {name "Srini" empid "10000"})
2
name is a clojure function from core. you want keywords all the way in your maps.cfrick
@cfrick You mean map key should be keyword(:)?Srini
Yes. Clojure let you create maps with symbols and vars as keys, but that is most of the time not what you want.cfrick
@cfrick When I ran this code the same issue coming (def my-map {flower1 :flower1 flower2 :flower2})Srini
@cfrick I don't see any issue with this code (let [{flower1 :flower1 flower2 :flower2} {:flower1 "red" :flower2 "blue"}] (str "The flowers are " flower1 " and " flower2))Srini

2 Answers

2
votes

Clojure is trying to resolve empid and can't, so it returns an error.

Clojure allows you to define maps with most anything as a key. This includes keywords and strings, which are very common, but also symbols, functions, numbers, data structures such as vectors and other maps, and more.

Your example contains one valid mapping, that is, the function bound to name which maps to the string "Srini". However, the other mapping is invalid because empid is not bound to anything.

The most common case is to use keywords for your keys, which have a particular advantage of allowing the values to be accessed via the keywords in a safe (non-NullPointerException-causing) way:

(:name {:name "Srini" :empid 10000})
=> "Srini"

So, while there may be a case where you'd want to map a function to something, this is clearly not the right way for you here. (as an aside, strings as keywords are particularly useful when reading from a file or database where the data is already a string and there's no advantage to converting to and from a keyword.

0
votes

You probably want to change your keys to keywords. In Clojure keywords are written with a colon in front of a string, but you don't need the quotes (as long as your keyword has no spaces in it, but let's not get complicated).

I recommend starting simply:

(def my-map {:name "george"})

This will create a map with a single key and value in it.

If you want to use let, do it like so:

(let [my-map {:name "george"}] my-map)

Update: Hm you seemed to have changed your question a fair bit! I still really recommend starting simply.

name is already defined as a function in clojure (it gets the string version of a symbol or keyword), so you shoudln't use that. Use :name if you want to create a key, unless you want to shadow the name "name" in a let binding, but that's nothing to do with keys in maps.

I feel like perhaps you need to learn the basics of maps and let before you go crazy with examples. Stick to simple things, and make sure your keys are not symbols.