lisp的功能還是挺強大的,簡單的幾十行代碼就搞定了一個小的“數據庫”(經驗:調試macro的時候可以用macroexpand-1展開該macro,看是否與設想的一樣)。
感受一下lisp吧:
CL-USER> (load "D:/database.lisp")
T
CL-USER> (add-cds)
Title: hacker
Artist: PG
Rating: 10
Ripped[y/n]: (y or n) y
Another? [y/n]: (y or n) n
NIL
CL-USER> (save-db "D:/save.db")
((:TITLE "hacker" :ARTIST "PG" :RATING 10 :RIPPED T))
CL-USER> (add-cds)
Title: painter
Artist: PG
Rating: 10
Ripped[y/n]: (y or n) y
Another? [y/n]: (y or n) n
NIL
CL-USER> (dump-db)
TITLE: painter
ARTIST: PG
RATING: 10
RIPPED: T
TITLE: hacker
ARTIST: PG
RATING: 10
RIPPED: T
NIL
CL-USER> (select (where :title "hacker"))
((:TITLE "hacker" :ARTIST "PG" :RATING 10 :RIPPED T))
CL-USER> (update (where :title "painter") :title "paint")
((:TITLE "paint" :ARTIST "PG" :RATING 10 :RIPPED T)
(:TITLE "hacker" :ARTIST "PG" :RATING 10 :RIPPED T))
代碼出自practical common lisp 一書,有改動~
(defvar?*db*?nil)
(defun?make-cd?(title?artist?rating?ripped)
??(list?:title?title?:artist?artist?:rating?rating?:ripped?ripped))
(defun?add-record?(cd)?(push?cd?*db*))
(defun?dump-db?()
??(dolist?(cd?*db*)
????(format?t?"~{~a:~10t~a~%~}~%"?cd)))
(defun?prompt-read?(prompt)
??(format?*query-io*?"~a:?"?prompt)
??(force-output?*query-io*)
??(read-line?*query-io*))
(defun?prompt-for-cd?()
??(make-cd?
???(prompt-read?"Title")
???(prompt-read?"Artist")
???(or?(parse-integer?(prompt-read?"Rating")?:junk-allowed?t)?0)
???(y-or-n-p?"Ripped[y/n]:?")))
(defun?add-cds?()
??(loop?(add-record?(prompt-for-cd))
?????(if?(not?(y-or-n-p?"Another??[y/n]:?"))?(return))))
(defun?save-db?(filename)
??(with-open-file?(out?filename?:direction?:output?:if-exists?:supersede)
????(with-standard-io-syntax
??????(print?*db*?out))))
(defun?load-db?(filename)
??(with-open-file?(in?filename)
????(with-standard-io-syntax
??????(setf?*db*?(read?in)))))
(defun?select?(selector-fn)
??(remove-if-not?selector-fn?*db*))
(defun?make-comparison-expr?(field?value)
??`(equal?(getf?cd?,field)?,value))
(defun?make-comparisons-list?(fields)
??(loop?while?fields
???????collecting?(make-comparison-expr?(pop?fields)?(pop?fields))))
(defmacro?where?(&rest?clauses)
??`#'(lambda?(cd)?(and?,@(make-comparisons-list?clauses))))
;(defun?where?(&key?title?artist?rating?(ripped?nil?ripped-p))
;??#'(lambda?(cd)
;??????(and
;???????(if?title????(equal?(getf?cd?:title)?title)?t)
;???????(if?artist???(equal?(getf?cd?:artist)?artist)?t)
;???????(if?rating???(equal?(getf?cd?:rating)?rating)?t)
;???????(if?ripped-p?(equal?(getf?cd?:ripped)?ripped)?t))))
(defun?make-set-expr?(field?value)
??`(setf?(getf?row?,field)?,value))
(defun?make-set-list?(fields)
??(loop?while?fields
???????collecting?(make-set-expr?(pop?fields)?(pop?fields))))
(defmacro?update?(selector-fn?&rest?clauses)
??`(setf?*db*
?????(mapcar
?????#'(lambda?(row)?
?????????(when?(funcall?,selector-fn?row)?,@(make-set-list?clauses))
?????????row)?*db*)))
?????
;(defun?update?(selector-fn?&key?title?artist?rating?(ripped?nil?ripped-p))
;??(setf?*db*
;????(mapcar
;?????#'(lambda?(row)
;?????????(when?(funcall?selector-fn?row)
;???????????(if?title????(setf?(getf?row?:title)?title))
;???????????(if?artist???(setf?(getf?row?:artist)?artist))
;???????????(if?rating???(setf?(getf?row?:rating)?rating))
;???????????(if?ripped-p?(setf?(getf?row?:ripped)?ripped)))
;?????????row)?*db*)))
(defun?delete-rows?(selector-fn)
??(setf?*db*?(remove-if?selector-fn?*db*)))
posted on 2010-10-01 22:23
hex108 閱讀(1008)
評論(0) 編輯 收藏 引用 所屬分類:
Lisp