我想创建一个函数来保存我认为是垃圾邮件的字符串的频率。我正在尝试使用可以更新的原子地图,因为我给地图一个新的字符串。
所需行为
user> (train-word spam "FREE")
{"FREE": 1}
user> (train-word spam "FREE")
{"FREE" : 2}
user> (train-word spam "MONEY")
{"FREE" : 2 "MONEY" : 1}
到目前为止,我已经尝试了
(def spam (atom {}))
(defn train-word [m word]
(swap! update-in m [word]
(fn [old] (inc (or old 0)))))
但是会产生错误:
clojure.lang.Atom cannot be cast to clojure.lang.Associative clojure.lang.RT.assoc (RT.java:702)
我是Clojure的新手,所以我在Python中做了一个快速原型
from collections import defaultdict
spam = defaultdict(int)
def train_word(word, spam):
spam[word] += 1
使用原子管理状态以更新当前值以及添加新值的惯用方法是什么?谢谢!
答案 0 :(得分:8)
只需要在调用swap!
的函数之前传递atom。
user> (def spam (atom {}))
#'user/spam
user> (defn train-word [m word]
(swap! m update-in [word]
(fn [old] (inc (or old 0)))))
#'user/train-word
user> (train-word spam "FREE")
{"FREE" 1}
swap!
通过以下方式构造函数调用:
(update-in [word] (fn [old] (inc (or old 0)))
@m
(update-in @m [word] (fn [old] (inc (or old 0)))
{"FREE" 1}