首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >封装在已定义函数中的Clojure Atom不更新

封装在已定义函数中的Clojure Atom不更新
EN

Stack Overflow用户
提问于 2017-12-21 01:39:32
回答 1查看 272关注 0票数 2

不确定这里发生了什么,但我有以下代码,其中map函数成功地在repl中执行,而不被包装在定义的函数中:

代码语言:javascript
复制
(def dogs '({:name "scout" :age 5} {:name "rux" :age 3} {:name "fenley" :age 2}))

(def ages (atom {:above-four '() :below-four '()}))

(map
    #(if (> (get-in % [:age]) 4)
         (swap! ages update-in [:above-four] merge %)
         (swap! ages update-in [:below-four] merge %)) dogs)

@ages
=> {:above-four ({:name "scout", :age 5}), :below-four ({:name "fenley", :age 2} {:name "rux", :age 3})}

然而,当我将map函数定义为这样时:

代码语言:javascript
复制
(def ages (atom {:above-four '() :below-four '()}))

(def dogs '({:name "scout" :age 5} {:name "rux" :age 3} {:name "fenley" :age 2}))

(defn test-dogs []
    (map
    #(if (> (get-in % [:age]) 4)
         (swap! ages update-in [:above-four] merge %)
         (swap! ages update-in [:below-four] merge %)) dogs)
         @ages)

我得到以下结果:

代码语言:javascript
复制
=> {:above-four (), :below-four ()}

我非常困惑,因为这个函数直接取自Clojure文档,运行得很好:

代码语言:javascript
复制
(def m1 (atom {:a "A" :b "B"}))

(defn update-m1 []
    (swap! m1 assoc :a "Aaay")
    @m1)

=> {:a "Aaay", :b "B"}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-21 02:29:36

因为test-dogs使用map,所以它返回一个惰性序列。懒惰序列的元素直到需要时才会实现。

设置的问题在于,您试图使用map运行一个副作用(调用swap!;一个不纯的操作),而从未实际使用map的结果。因为您从不请求map的结果,所以包含swap!的映射函数永远不会运行。

通过使用mapv (返回一个非惰性向量)或doseq (这意味着执行副作用):

代码语言:javascript
复制
(doseq [dog dogs]
  (let [k (if (> (:age dog) 4)
                :above-four
                :below-four)]

     (swap! ages update k merge dog))) 

您可以强制运行副作用。

我把密码弄干净了一点。您使用的-in版本是不必要的;对get-in的调用也是不必要的。我还取消了对swap!的冗余调用。

注意,至少在您的示例中,使用atom是完全不必要的。即使您有一个更复杂的用例,也要确保它们的使用是合理的。可变变量在Clojure这样的语言中并不常见。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47916733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档