我正在阅读Peter Siebel的书Simple Database的Practical Common Lisp部分,想要维护一个包含大约50,000条记录的小型数据库。我认为在Emacs中这样做可能是一个有趣且有用的练习。除了少数notable differences之外,Emacs Lisp与CL有些兼容。上面示例中使用的格式函数是一个主要区别。
这是包含在CL中构建,保存和加载数据库所需的所有内容的代码。这可以修改为在Emacs中运行良好吗?我省略了选择和其中功能,但我想要包含它们。也许有更好的Emacs方式来构建和维护数据库?就个人而言,我将此作为练习来学习CL并解决现有问题。
;; Simple Common Lisp database ;; http://www.gigamonkeys.com/book/practical-a-simple-database.html ;; (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 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))))) ; === ; ; Add some records ; (add-record (make-cd "Roses" "Kathy Mattea" 7 t)) (add-record (make-cd "Fly" "Dixie Chicks" 8 t)) (add-record (make-cd "Home" "Dixie Chicks" 9 t)) ; (dump-db) ; (save-db "cd.db") ; (load-db "cd.db")
答案 0 :(得分:3)
这是我的解决方案:
(defvar *db* nil)
(setq *db* ())
(defun make-cd (title artist rating ripped)
(list :title title :artist artist :rating rating :ripped ripped))
(defun add-record (cd) (push cd *db*))
(defun init ()
(progn
(add-record (make-cd "Roses" "Kathy Mattea" 7 t))
(add-record (make-cd "Fly" "Dixie Chicks" 8 t))
(add-record (make-cd "Home" "Dixie Chicks" 9 t))
))
(defun save-db (filename)
(with-temp-buffer
(print *db* (current-buffer))
(write-file filename))
(message "Saving database...done")
)
(defun load-db (filename)
(with-temp-buffer
(insert-file-contents filename)
(setq *db* (read (current-buffer)))))
(defun dump-db ()
(dolist (cd *db*)
(print cd)))
;; Test in M-x lisp-interaction-mode
;;(init)
;;(save-db "cd.db")
;*db*
;(add-record (make-cd "Born To Run" "Bruce Springsteen" 10 t))
;(add-record (make-cd "The River" "Bruce Springsteen" 10 t))
;(add-record (make-cd "Nebraska" "Bruce Springsteen" 10 t))
;(add-record (make-cd "Human Touch" "Bruce Springsteen" 10 nil))
;;(save-db "cd.db")
;(setq *db* ())
;;(load-db "cd.db")
;*db*
答案 1 :(得分:2)
当我尝试为Emacs编写电子书库时,我将记录存储在列表中,并不时将其保存到磁盘。当列表长度超过大约五千条记录时,性能受到影响。
以下是代码中的一些函数:
(defun bread-library-load-db ()
"Loads the list of books from disk file to the variable bread-library-db"
(if (file-exists-p bread-library-file)
(with-temp-buffer
(insert-file-contents bread-library-file)
(setq bread-library-db (read (current-buffer))))
(setq bread-library-db '())))
(defun bread-library-add-book (file)
"Attempts to get metadata from file, then prompts for
confirmation (or modification) of these metadata, then adds the
book to the database and saves it. Intended use: from dired."
(if (assoc file bread-library-db)
(error "File is already in the database")
(progn
(let ((metadata (bread-get-metadata file)))
(let ((filename (nth 0 metadata))
(author (read-from-minibuffer
"Author: "
(nth 1 metadata)))
(title (read-from-minibuffer
"Title: "
(nth 2 metadata)))
(genre (read-from-minibuffer "Genre: " (nth 3 metadata)))
(tags (read-from-minibuffer "Tags (separated and surrounded by colons): " ":"))
(desc (nth 4 metadata)))
(setq bread-library-db (cons
(list filename author title tags "TOREAD" genre nil desc)
bread-library-db))))
(bread-library-save-db bread-library-db))))
(defun bread-library-save-db (db)
"Save the library database to a file."
(message "Saving Bread library database...")
(with-temp-buffer
(insert "; 1.path 2.author 3.title 4.tags 5.state 6.genre 7.priority 8.description")
(print db (current-buffer))
(write-file bread-library-file))
(message "Saving Bread library database...done"))