3
votes

I want to delete room by number. As you can see, the rooms is atom list and contains atoms. I got an exception: IllegalArgumentException Don't know how to create ISeq from: core.main$delete_room_by_id$fn__7541 clojure.lang.RT.seqFrom (RT.java:487)

I have this code:

(comment ------------- * DATA * ----------------- )
(def rooms "atomic list of atoms - rooms" (atom '()))

(comment ------------- * UTILS * ----------------- )

(defn enter-value [message]
     (do (println message) (read-line)))

(comment ------------- * ADD ROOM * ----------------- )

(defn save-room "The function that will save provided room." 
     [number num-of-beds price]
     (swap! rooms conj (atom {:number number 
                              :num-of-beds num-of-beds
                              :price price 
                              :is-ocupated false})))

(defn enter-room "This function will create room based on user input." []
     (let [number (enter-value "Number...")
           num-of-beds (enter-value "Number of beds...")
           price (enter-value "Price...")]
       (save-room number num-of-beds price)))

(comment ------------- * DELETE ROOM * ----------------- )

(defn delete-room-by-number "Delete room by number."
     [number]
     (swap! rooms remove #(not (= (:number @%) number))))

I think that swap! function don't put parameters for remove function as I want. I think that final command is: (remove rooms #(not (= (:number @%) number))). This is not good because I must to deref rooms like @rooms and pass it as second parameter of remove function.

Thanks for reading this.

1

1 Answers

7
votes

There is a mistake in two functions. The value in save-room should not be a map in an atom, but just a map, because else you get atoms saved in an atom. Also delete-by-room-number contained a mistake, the anonymous function wasn't written correctly.

(defn save-room "The function that will save provided room." 
           [number num-of-beds price]
           (swap! rooms conj {:number number :num-of-beds num-of-beds :price price :is-ocupated false}))

(defn delete-room-by-number [num]
     (swap! rooms #(remove (fn [room] (= (:number room) num)) %)))

Update:

It is more common practice to store an immutable, possibly nested, datatructure in an atom/ref,etc. A better option might be to not to go for a list but a vector or map, like this:

(def room-map {1 {:nums-of-beds 2 :price 30}, 2 {:nums-of-beds 4 :price 60}})

This way you use the room number as the key. This way you can never have a duplicate room number, because map keys must be unique.

You can update the map with assoc-in, update-in etc:

(def new-room-map (assoc-in room-map [2 :nums-of-beds] 40))

Value of new-room-map: {1 {:nums-of-beds 2, :price 30}, 2 {:nums-of-beds 40, :price 60}}

If you are going for the map representation of your rooms, use the function assoc-in in combination with swap! and an updated version of your room-map will be stored in the atom. If you have trouble understanding this, I suggest you read more on these functions:

http://clojuredocs.org/clojure_core/clojure.core/swap! http://clojuredocs.org/clojure_core/clojure.core/assoc-in