为什么clojure交换!与地图无法正常工作?

时间:2016-04-29 05:32:04

标签: clojure

(defn get-vector []
    (let [rs (atom [])]
        (map (fn [x] (swap! rs conj x)) [1 2 3 4]) 
      @rs))

(get-vector)

我认为这个函数应该返回[1 2 3 4]; 但是,它只返回一个空向量[]

2 个答案:

答案 0 :(得分:10)

Clojure map是懒惰的,因为你没有要求它的结果,它不会评估它的内容,也不会用swap!执行你的功能。

要使其正常运行,您应该使用dorun强制它实现其内容:

(defn get-vector []
  (let [rs (atom [])]
    (dorun (map (fn [x] (swap! rs conj x)) [1 2 3 4]))
    @rs))

(get-vector)
;; => [1 2 3 4]

我不确定您要解决的问题是什么 - 如果这只是一个示例代码来测试swap!的工作方式,那么该代码看起来还不错。否则,您可能希望使用其他解决方案,例如reduce,并避免使用可变引用。

根据@Shlomi的建议,使用doseq副作用更为惯用:

(let [rs (atom [])]
  (doseq [x [1 2 3 4]]
    (swap! rs conj x))
  @rs)

答案 1 :(得分:1)

doseq更惯用,但我更喜欢map的语法,所以另一种选择是创建一个强制序列实现的maprun

(def maprun (comp dorun map))

(defn get-vector []
  (let [rs (atom [])]
    (maprun (fn [x] (swap! rs conj x)) [1 2 3 4]) 
    @rs))

(get-vector)

这在技术上与Piotrek相同,因为maprun仅仅是语法糖。