日期:2014-05-16  浏览次数:20471 次

用clojure实现《实用Common Lisp编程》中的简单数据库:CD数据库
(ns simple-cd-database.core)

(defn make-cd
  [title artist rating ripped]
  {:title title :artist artist :rating rating :ripped ripped})

(def db (atom []))

(defn add-record [cd] (swap! db conj cd))

(defn dump-db
  []
  (doseq [cd @db]
    (doseq [[k v] cd]
      (prn k v))
    (prn)))

(add-record (make-cd "Home" "Dixie Chicks" 9 true))
(add-record (make-cd "Love" "Dixie Chicks" 8 true))
;(prn @db)
(dump-db)
;(prn @db)
(defn prompt-read [promt]
  (print promt ": ")
  (flush )
  (read-line))

(defn y-or-n-p [string]
  (if (re-find #"(?i)y" string) true false))

(defn parse-integer [str]
  (try (Integer/valueOf str)
    (catch NumberFormatException _ 0)))

(defn prompt-for-cd
  []
  (make-cd
    (prompt-read "Title")
    (prompt-read "Artist")
    (parse-integer (prompt-read "Rating"))
    (y-or-n-p (prompt-read "Ripped [y/n]"))))

(defn add-cds
  []
  (loop [_ (add-record (prompt-for-cd))]
    (if (y-or-n-p (prompt-read "Another? [y/n]"))
      (recur (prompt-for-cd)))))

;(add-cds )
;(dump-db)

(defn save-db
  [file-name]
  (spit file-name (pr-str @db)))

(defn load-db [filename]
  (reset! db (read-string (slurp filename))))

(save-db "cd.txt")
(load-db "cd.txt")
(dump-db )

(defn select [where-fn]
  (filter where-fn @db))

(defn dis-select [where-fn]
  (drop-while where-fn @db))

(defn where
  [& conditions]
  (fn [record]
    (let [condition-map (apply hash-map conditions)]
      (every? true?
        (for [ [condition value] condition-map]
          (= (condition record) value))))))

(select (where :artist "Dixie Chicks"))

(defn update
  [where-fn & new-value-map]
  (reset! db
    (map (fn
         [cd]
         (if (where-fn cd) (apply assoc cd new-value-map) cd)) @db)))

(update (where :title "Home") :artist "big bang")
(dump-db )