我是 clojure 的新手,并且正在通过从 Practical Common Lisp 重新创建 cd 项目来学习。我在使用 where 'clause' 选择器实现更新功能时遇到了麻烦。执行 (update (where :artist "AC/DC") :rating 10) 导致我的数据库被炸毁,只返回一个空列表。这是我的代码:
(defn where [& {:keys [title artist genre rating]}]
(fn [cd]
(and
(if title (= (get cd :title) title) true)
(if artist (= (get cd :artist) artist) true)
(if genre (= (get cd :genre) genre) true)
(if rating (= (get cd :rating) rating) true))))
(defn update [selector-fn & {:keys [title artist genre rating]}]
(def ^:dynamic *db*
(map (fn [row]
(when (apply selector-fn row)
(if title (def row (assoc-in row [:title] title)))
(if artist (def row (assoc-in row [:artist] artist)))
(if genre (def row (assoc-in row [:genre] genre)))
(if rating (def row (assoc-in row [:rating] rating))))
row)
*db*)))
我已将每张 CD 实现为哈希映射:
(defn make-cd [title artist genre rating]
{:title title
:artist artist
:genre genre
:rating rating
})
所以我认为我对 assoc-in 的使用是正确的。任何关于我做错了什么的想法将不胜感激。
谢谢...
美中
好的。根据 Arthur 的评论,我现在拥有的更新功能是:
(defn update [selector-fn & {:keys [title artist genre rating]}]
(map (fn [row]
(when (apply selector-fn row)
(-> row
(#(if title (assoc-in % [:title] title) %))
(#(if artist (assoc-in % [:artist] artist) %))
(#(if genre (assoc-in % [:genre] genre) %))
(#(if rating (assoc-in % [:rating] rating) %)))))
*db*))
我想我仍然需要map
表单,因为我需要遍历*db*
. 我不想只更改*db*
艺术家为 AC/DC 的所有 CD 的评级。somap
将遍历每个 cd (将其绑定到row
),然后调用该where
函数以查看标题是否匹配。如果是这样,那么它将返回 true 以允许更新评级。
不幸的是,这仍然不起作用。
ArityException Wrong number of args (4) passed to: core$where$fn clojure.lang.AFn.throwArity (AFn.java:437)