clojure - 在 Clojure 中过滤来自 Atom 的映射列表
问题描述
我正在开发一个迷你社交媒体 API,允许用户插入新的个人资料,将两个个人资料连接在一起(如朋友),然后根据“我朋友的朋友”规则接收推荐。
现在我正在尝试为 Profile 创建 API。
我有一个包含地图列表的原子,每个配置文件一个。
(def profiles (atom ()))
(defn create [request]
(swap! profiles conj {:id (get-in request [:body "id"])
:name (get-in request [:body "name"])
:age (get-in request [:body "age"])
:recommendable (get-in request [:body "recommendable"])
:friends (list)
})
(created "")
)
当我偶然发现一个问题时,我试图为 API 的 GET http 动词开发 find-by-id。如何从所述列表中的地图中获取值,以便我可以对其应用函数?
例如,在这里我试图使用过滤器函数只返回包含给定 id 的地图。但我不断收到错误消息:
(defn find-by-id [id]
(filter #(= (:id %) id) profiles)
)
Dont know how to create ISeq from: clojure.lang.Atom
在我看来,过滤器不适用于 Atom。
同样的事情发生在删除:
(defn delete-by-id [id]
(swap! profiles (remove #(= (:id %) id) profiles))
)
当我尝试使用@profiles 时,我得到一个空数组。更糟糕的是,当我尝试使用 REPL 的过滤器功能时,它工作得很好。
这让我想知道我在这里错过了什么。
谁能告诉我发生了什么?
提前致谢。
解决方案
第一个失败了,因为正如它所说,原子不是filter
预期的序列。
您需要先从原子中取出序列filter
:
; I'm dereferencing the atom using @ to get the list of profiles that it holds
(defn find-by-id [id]
(filter #(= (:id %) id) @profiles))
但请注意,这不是最佳选择。您依赖的状态profiles
可能会在看似随机的时间发生变化(如果您有异步进程swap!
ping 它)。这可能会使调试复杂化,因为在数据传递到filter
. 函数依赖于原子也是不好的profiles
,因为这与它的功能无关,你以后可能会改变你的设计。让这个函数完全依赖于它的参数并且对原子一无所知,这将是更多的未来证明:
(defn find-by-id [id profiles]
(filter #(= (:id %) id) profiles))
; Then call it like this. I renamed your atom here
(find-by-id some-id @profile-atom)
您的第二个示例失败,因为swap!
接受一个函数作为其第二个参数。我认为您的意思是使用reset!
,它会改变原子的值,而不管它以前是什么:
(defn delete-by-id [id]
(reset! profiles (remove #(= (:id %) id) @profiles)))
虽然,这也不是最优的。如果要根据先前的状态更新原子,请swap!
改用并提供更新函数:
(defn delete-by-id [id]
(swap! profile-atom (fn [profiles] (remove #(= (:id %) id)) profiles)))
或者,稍微简洁一点:
(defn delete-by-id [id]
(swap! profile-atom (partial remove #(= (:id %) id))))
我正在部分申请remove
制作功能。原子的旧状态作为最后一个参数传递给remove
.
推荐阅读
- python - 为什么使用 python websocket 连接到 websocket 时会收到 400 Bad Request,而使用 Burp Suite 时会收到 101 Switching Protocols?
- gulp - 在 Gruntfile 中使用变量对象
- clojure - 在 Datomic 中,查询没有撤回的字段历史记录?
- android - 仅在 Android 11 上创建一次的文件
- python - 如何终止一个python线程?
- node.js - 需要安装'webpack-dev-server'
- r - 整理:!!使用 purrr::map 匿名函数
- qt - 使用附加属性、信号的正确方法是什么?
- rust - 为什么在 rust 程序中运行 objcopy --strip-all 会使它们的大小减半?
- django - 在 Django 管理页面中创建用户时有条件地需要密码