3

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 Answer 1

7

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

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for answer. I wanted to have atoms in atom because I need ability to change values in each room. Is it bad? I'm student and I'm in learning process. Thanks Michiel.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.