Search code examples
clojureclojurescript

Clojure - Changing the value of an atom in a different function


I know that Clojure is all about immutable data. So if you have an atom (say with value 0), the way to change it's value is to de-reference the atom and use swap! or reset! (say now with value 1). However, globally the atom still has value 0 and in the specific reset! or swap! function it has value 1. (I believe this to be correct). My question is, can I have another function that changes the value of the atom which is at 1.

More clearly

(def table-data {:headers ["RIC-Code" "Isin" "Currency" "Description"]
                 :rows []})

(defonce fields (atom {}))
(defonce errors (atom nil))
(defonce isin (atom "test")
(defonce tdata (atom table-data))


(defn get-ric [ric isin]
  (GET "/search-isin"
       {:params {:ric ric}
        :headers {"Accept" "application/transit+json"}
        :handler #(do
                   (.log js/console (str "get-msg response : " %))
                   (reset! isin %)
                   (reset! tdata {:headers ["RIC-Code" "Isin" "Currency" "Description"]
                                  :rows    @isin}))}))



(defn replace-value [struct]
  (walk/prewalk-replace {"id" "name"} struct))
(defn isin-form2 [isin]
  [:div.content
   [errors-component errors :server-error]
   [:div.form-group
    [errors-component errors :name]
    [:p "Enter RIC-Code:"
     [:input.form-control
      {:type      :text
       :name      :ric
       :on-change #(swap! fields assoc :ric (-> % .-target .-value))
       :value     (:ric @fields)}]]
    [errors-component errors :message]
    [:input.btn.btn-primary
     {:type     :submit
      :on-click #(do
                  (get-ric (:ric @fields) isin))
      :value    "Search RIC-Code"}]
    [rt/reagent-table tdata]
    [:input.btn.btn-primary
     {:type     :submit
      :on-click #(do
                  (reset! tdata {:headers ["RIC-Code" "Isin" "Currency" "Description"]
                                 :rows    (swap! isin (replace-value %))}))
      :value    "Change"}]]])

What the above code does, is in isin-form2, it takes an initial value, and sets in into fields with keyword ric. The first button calls the get-ric function and returns tdata. (In get-ric the isin is an atom that is a vector of vectors ie [["id" ...] [...] ... [...]]) What I want the second button to do is swap the value id for name, using replace-value. However in the second button when I try to swap! the value of the isin it is not changing


Solution

  • Perhaps this will explain how it works:

    (def my-state (atom 0))
    
    (defn fn1 [] 
      (newline)
      (println :fn1-enter @my-state)
      (swap! my-state inc)
      (println :fn1-exit  @my-state)
      (newline))
    
    (defn fn2 [] 
      (newline)
      (println :fn2-enter @my-state)
      (swap! my-state inc)
      (println :fn2-exit  @my-state)
      (newline))
    
    (println :main-1 @my-state)
    (fn1)
    (println :main-2 @my-state)
    (fn2)
    (println :main-3 @my-state)
    

    with result

    :main-1 0
    
    :fn1-enter 0
    :fn1-exit 1
    
    :main-2 1
    
    :fn2-enter 1
    :fn2-exit 2
    
    :main-3 2