我正在尝试通过添加书中描述的 select - 函数来调整此defstruct示例:Practical Common Lisp。我正在使用Common Lisp包在Emacs中运行代码。 select-by-first 不会返回任何内容。在Lisp书中,作者不使用defstruct,所以我必须做一些稍微不同的事情?
(defun select-by-first (first-name) (remove-if-not #'(lambda (employee) (equal (getf employee :first-name) first-name)) *emp-db*)) (select-by-first "steve")
完整的计划:
(require 'cl)
;; http://mypage.iu.edu/~colallen/lp/node56.html
;; http://www.gigamonkeys.com/book/practical-a-simple-database.html
;;
(defvar *emp-db* nil)
(defun add-record (emp) (push emp *emp-db*))
(defstruct employee
age
first-name
last-name
sex
children)
(add-record (make-employee))
(add-record (make-employee
:age 34
:last-name 'farquharson
:first-name 'alice
:sex 'female))
(add-record (make-employee
:age 43
:last-name 'jobs
:first-name 'steve
:sex 'male))
(add-record (make-employee
:age 53
:last-name 'ballmer
:first-name 'steve
:sex 'male))
(defun select-by-first (first-name)
(remove-if-not
#'(lambda (employee)
(equal (getf employee :first-name) first-name))
*emp-db*))
(select-by-first "steve")
答案 0 :(得分:4)
有一些基本的错误/问题。但只有两个小的改动,我们可以让你的例子在Common Lisp中工作。
Emacs Lisp的Common Lisp兼容包并不是一个真正的Common Lisp。通常最好使用真正的Common Lisp实现。 Emacs Lisp缺少一些难以模仿以使其与Common Lisp兼容的基本内容 - 例如词法闭包(更新2014,最新版本的GNU Emacs现在也支持词法闭包)。
小改动:我改变了你的例子,以便数据库不包含史蒂夫乔布斯两次,但史蒂夫乔布斯和史蒂夫鲍尔默。
现在,我们需要改变什么才能使它在Common Lisp中运行?
(getf employee:first-name)应该是(员工名字员工)。 DEFSTRUCT宏自动生成这些访问器函数。在Common Lisp中,您无法使用GETF访问实际结构的字段。
您的数据库有两个名为STEVE(符号)的对象,但您正在搜索名称“steve”(字符串)。 (等于'史蒂夫'史蒂夫“)是假的。通常,符号与字符串不相等。所以你应该搜索(先选择'steve)。
在LispWorks中:
CL-USER 11 > (select-by-first "steve")
NIL
CL-USER 12 > (select-by-first 'steve)
(#S(EMPLOYEE :AGE 53 :FIRST-NAME STEVE :LAST-NAME BALLMER :SEX MALE
:CHILDREN NIL)
#S(EMPLOYEE :AGE 43 :FIRST-NAME STEVE :LAST-NAME JOBS :SEX MALE
:CHILDREN NIL))
答案 1 :(得分:1)
谢谢Rainer。这是在Emacs中运行的已完成代码。
#!/usr/bin/emacs --script ;; Derived from code on these sites: ;; ;; http://mypage.iu.edu/~colallen/lp/node56.html ;; http://www.gigamonkeys.com/book/practical-a-simple-database.html ;; (require 'cl) (defvar *emp-db* nil) (defun add-record (emp) (push emp *emp-db*)) (defstruct employee age first-name last-name sex children) (add-record (make-employee)) (add-record (make-employee :age 34 :last-name 'farquharson :first-name 'alice :sex 'female)) (add-record (make-employee :age 43 :last-name 'jobs :first-name 'steve :sex 'male)) (add-record (make-employee :age 53 :last-name 'ballmer :first-name 'steve :sex 'male)) (defun select-by-first (first-name) (remove-if-not #'(lambda (employee) (equal (employee-first-name employee) first-name)) *emp-db*)) (defun select-by-last (last-name) (remove-if-not #'(lambda (employee) (equal (employee-last-name employee) last-name)) *emp-db*)) (princ "Employees with the first name Steve:\n") (princ " ") (princ (select-by-first 'steve)) (princ "\n") (princ "Employees with the last name Jobs:\n") (princ " ") (princ (select-by-last 'jobs)) (princ "\n")