문제

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?

도움이 되었습니까?

해결책

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.

다른 팁

As Ankur mentioned it's better to use doseq for imperative operations:

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

But you can force evaluation of the map result by using dorun in your original version:

(let  [ myAtom  (atom {})]    
  (dorun (map #(when (== %1 %2) (swap! myAtom assoc %1 %2 ))
              [1 2 3] [4 5 3])) 
  (prn @myAtom))

P.S. Ankur's version is not equivalent to original one

doseq:

(doseq [a [1 2 3]
        b [4 5 3]]
  (println [a b]))

=> [1 4]
   [1 5]
   [1 3]
   [2 4]
   [2 5]
   [2 3]
   [3 4]
   [3 5]
   [3 3]

map:

(dorun (map #(println [%1 %2]) 
            [1 2 3]
            [4 5 3]))

=> [1 4]
   [2 5]
   [3 3]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top