【问题标题】:Clojure swap! not working inside a map function in let bindingsClojure 交换!在 let 绑定中的 map 函数内不起作用
【发布时间】:2013-02-26 06:14:00
【问题描述】:

我有两个要比较的序列,我需要将比较结果保存在映射中,第一个序列中的数据用作键,第二个序列中的数据用作 val。下面是可以工作的示例代码

(def myAtom  (atom {}))

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

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

但是,将上面的“相同”的东西放入一个 let 绑定后,它就不再起作用了

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

所以问题是,在 let 绑定中 myAtom 会发生什么?怎么不见了?

【问题讨论】:

  • 如果没有“else”分支,你可以使用when而不是if

标签: dictionary clojure swap let


【解决方案1】:

map 是从序列中生成惰性序列,而您需要对序列中的每个项目执行某些操作(即交换),因此您需要使用doseq

编辑:(更新为@mobyte 建议)

(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))

您的第一个示例有效,因为您在 REPL 中执行了每个表达式,这使得 map 操作执行其惰性操作。

我见过很多人尝试使用 map 来做这样的某些操作,map 应该只用于一个目的,即将一个序列映射到另一个序列而没有任何副作用操作。

【讨论】:

    【解决方案2】:

    正如 Ankur 所说,最好使用 doseq 进行命令式操作:

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

    但您可以在原始版本中使用 dorun 强制评估地图结果:

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

    P.S. Ankur 的版本不等同于原版

    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]
    

    【讨论】:

    • 感谢 mobyte 这很有帮助!
    猜你喜欢
    • 2013-05-31
    • 2013-02-13
    • 2018-08-27
    • 1970-01-01
    • 2014-03-21
    • 2014-06-19
    • 2015-11-20
    • 2013-01-03
    • 1970-01-01
    相关资源
    最近更新 更多