Search code examples
dictionaryclojureswaplet

Clojure swap! not working inside a map function in let bindings


I have two sequences for comparison and I need to keep comparison results in a map, with data in the first sequence serving as keys and second as vals. Here comes sample code that works

(def myAtom  (atom {}))

(map #(if (== %1 %2) (swap! myAtom assoc %1 %2 ))
              [1 2 3]   [4 5 3]) 

(prn @myAtom)  ; ==>  {3 3}

However after putting "same" thing above into one let bindings, it doesn't work anymore

(let  [ myAtom  (atom {})]    
  (map #(if (== %1 %2) (swap! myAtom assoc %1 %2 ))
              [1 2 3]   [4 5 3]) 
  (prn @myAtom)) ;;==> {} empty???

So the question is, what happens to myAtom inside let binding? How come is it missing?


Solution

  • map is to generate lazy sequence out of a sequence whereas what you need is to do certain operation (i.e swap) for each item in a sequence, hence you need to use doseq

    EDIT: (updated as par @mobyte suggestion)

    (let  [myAtom  (atom {})
           a [1 2 3]
           b [4 5 3]]    
      (doseq [[x y] (map vector a b)]
        (if (== x y) (swap! myAtom assoc x y )))
      (prn @myAtom))
    

    Your first example works because you executed each expression in REPL which made the map operation to execute its lazy operations.

    I have seen many people try to use map to do certain operations like this, map should only be used for one purpose i.e mapping a sequence to another sequence without any side-effect operations.