0
votes

I am doing my second homework working with Clojure and am having difficulty getting a value at a specified index from a hash map. Currently I have a function to create a vector of hash maps that represent a graph. I then index into that vector to get a specific hash map representing a node, specifically the nodes connections to other nodes; as such

homework2.core> (reg-ring-lattice 5 2)  
[#{1 4} #{0 2} #{1 3} #{4 2} #{0 3}] 
homework2.core> ((reg-ring-lattice 5 2) 2)
#{1 3} 

My issue is iterating over the values in the hash map itself. I would specifically like to retrieve the nth index from the hash map. Here is what I have tried

homework2.core> ((reg-ring-lattice 5 2) 3) 
#{4 2}
homework2.core> (((reg-ring-lattice 5 2) 3) 0) 
nil
homework2.core> (get ((reg-ring-lattice 5 2) 3) 0) 
nil

I have searched but currently my knowledge of Clojure and its keywords/jargon is limited.

The first question is, am I calling these collections by their proper names. Second, how can I retrieve a value at a specified index in what I am calling a hashmap?

3
What are your intentions here? It seems like you're unfamiliarity with Clojure is getting in the way of getting the help you're after. Perhaps if you give some more detail about what you are doing or how you would like it to work we could help more.A Sammich

3 Answers

2
votes

those are no hash MAPS but hash SETS and they are not sorted. You would get a "random" element on sequential/indexed access. E.g.

user=> (first #{1 2 3 4 5})
1
user=> (second #{1 2 3 4 5})
4
2
votes

A hash-map is a dictionary, key/value pairs. They show up in the output surrounded in curly braces -> {}. A set is something like a list but must contain unique items. Sets show up in the output surrounded by an octothorpe with curly braces -> #{}. Vectors are structures that contain items in an indexed sequence. They show up in the output surrounded in square braces -> [].

See hash-maps at the clojure.org docs, sets at the clojure.org docs, and vectors at the clojure.org docs.

Your reg-ring-lattice function is returning a vector of sets. It doesn't make much sense to index into a set made up of numbers like you have so let me go over what you are doing in your example code blocks.

;This output is a vector of sets
(reg-ring-lattice 5 2)
[#{1 4} #{0 2} #{1 3} #{4 2} #{0 3}]

;This output exploits the fact that vectors implement IFn (see the doc links)
; Surrounding the call in another set of parens makes another call the argument
; of which is '2'. You seem to have a good grasp on all this so far.
((reg-ring-lattice 5 2) 2) ; returns the item at index 2 in the vector
#{1 3}

;This is exactly the same as the above except for getting the item at index 3.
((reg-ring-lattice 5 2) 3)
#{4 2}

;This is what doesn't make sense. Sets are functions of their members. They
;aren't indexed like vectors are
(((reg-ring-lattice 5 2) 3) 0)
; What you are saying here is 'give me item 0, not index 0, out of the set
; returned from looking into the vector at index 3 or nil if not found'.
; It would work if your set had a 0 in it or if you did this:
(((reg-ring-lattice 5 2) 3) 4) ; -> returns 4
; but it's not too helpful because you already know what you're looking up.

;Instead, this is where you start treating the returned set like a list
(first ((reg-ring-lattice 5 2) 3)) ; -> returns 4
(second ((reg-ring-lattice 5 2) 3)) ; -> returns 2

One thing to be wary of with sets, which you can ignore if you are generating sorted sets, they may not be sorted. What is first last time may not be first next time. Another thing to watch for is duplicates. Each item in a set must be unique. You can't have a set like this -> #{4 4}.

1
votes

As others have pointed out, you are using a vector of sets, not of maps.

Calling a set as a function will return the argument, if it's in the set, otherwise nil:

(#{2 3 4} 1) ;nil
(#{2 3 4} 2); 2

You would like to retrieve the nth element from a set:

(nth (seq #{2 3 4}) 1)
;3

The order may not be what you expect:

(seq #{4 2 3})
; (2 3 4)

But why do you want the nth element anyway? You can enumerate the elements of the set by calling seq on it (implicitly, if you're using functions such as map and reduce). If you show us what you are trying to do, it's likely there's a more idiomatic way to do it. And nth is slow - it tells the sequence element by element.

By the way, by using a vector of sets you are tying yourself to graphs with nodes labelled 0 to n. A map of sets is often a better choice:

{4 #{0 3}, 3 #{2 4}, 2 #{1 3}, 1 #{0 2}, 0 #{1 4}}

... instead of ...

[#{1 4} #{0 2} #{1 3} #{4 2} #{0 3}]