私はclojureを初めて使用し、PracticalCommonLispから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の使い方は正しいと思っています。私が間違っていることについてのアイデアは大歓迎です。
ありがとう...
MZ
Ok。アーサーのコメントに基づいて、ここに私が今更新機能のために持っているものがあります:
(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だけですべてのCDの評価を変更したくありません。したがってmap
、各cdを繰り返し処理し(にバインドrow
)、where
関数を呼び出してタイトルが一致するかどうかを確認します。その場合、trueが返され、評価を更新できます。
残念ながら、これはまだ機能しません。
ArityException Wrong number of args (4) passed to: core$where$fn clojure.lang.AFn.throwArity (AFn.java:437)