I am new to Clojure and functional programming. I have a basic idea about the data structures in Clojure such as maps, lists, and vectors.
I am trying to write a function that returns a nested map. The map is correctly displayed inside the function. The below code is from the read-customer-file function
([input-list new-map place-holder]
(if (not-empty input-list)
(do
(def string-input (str (first input-list)))
(def cust-id (get (first input-list) 0))
(def cust-name (get (first input-list) 1))
(def cust-address (get (first input-list) 2))
(def cust-phone (get (first input-list) 3))
(def temp-map (conj new-map {(keyword cust-id) {:cust-name cust-name, :cust-address cust-address, :cust-phone cust-phone}}))
(read-customer-file (rest input-list) temp-map ())
)
(do
(map str new-map)
;(print (get-in new-map [:1 :cust-name]))
(print new-map)
)
)
)
This takes an input of list of vectors as below:
([3 Fan Yuhong 165 Happy Lane 345-4533] [2 Sue Jones 43 Rose Court Street 345-7867] [1 John Smith 123 Here Street 456-4567])
and returns a nested-map as below:
{:3 {:cust-name Fan Yuhong, :cust-address 165 Happy Lane, :cust-phone 345-4533}, :2 {:cust-name Sue Jones, :cust-address 43 Rose Court Street, :cust-phone 345-7867}, :1 {:cust-name John Smith, :cust-address 123 Here Street, :cust-phone 456-4567}}
This is what I am trying to achieve and is working perfectly fine within the function. However, if I try to define a variable outside the function with the value of the return type, I do not get a nested-map but a list of strings. For this, I just remove the (print new-map) part.
(do
(map str new-map)
)
And call it from outside the function definition as follows:
(def customer-info-list read-customer-file)
(println (customer-info-list))
The result I get is different from what I expected and cannot perform the map-related functionalities such as get and get-in.
([:3 {:cust-name Fan Yuhong, :cust-address 165 Happy Lane, :cust-phone 345-4533}] [:2 {:cust-name Sue Jones, :cust-address 43 Rose Court Street, :cust-phone 345-7867}] [:1 {:cust-name John Smith, :cust-address 123 Here Street, :cust-phone 456-4567}])
I would very much appreciate any kind of help with this. I am aware that my code is a bit messy and I should use let instead of def for variable names. But I am just starting Clojure and this is my first program.
UPDATE
I solved the problem. What I did is change the map into a sorted-map inside the function. So the last return from the function will be a sorted map.
(do
(into (sorted-map) new-map)
)
However, the returned value will still be a string if assigned to a variable., so I converted it to a sorted-map once again. Then it finally got converted to a nested-map.
(def customer-info-list read-customer-file)
(def cust-map (into (sorted-map) (customer-info-list)))
(println cust-map)
(println (get-in cust-map [:1 :cust-name]))
(println (get cust-map :2))
The output from the above three print statements is as expected.
{:1 {:cust-name John Smith, :cust-address 123 Here Street, :cust-phone 456-4567}, :2 {:cust-name Sue Jones, :cust-address 43 Rose Court Street, :cust-phone 345-7867}, :3 {:cust-name Fan Yuhong, :cust-address 165 Happy Lane, :cust-phone 345-4533}}
John Smith
{:cust-name Sue Jones, :cust-address 43 Rose Court Street, :cust-phone 345-7867}
def-ing inside your function is usually something you don't want to do. Useletinstead.