使用带有remove-if-not 的defstruct 数据库

2 elisp common-lisp

我试图通过添加《 Practical Common Lisp》一书中描述的选择函数来修改这个defstruct示例。我正在使用 Common Lisp 包在 Emacs 中运行代码。select -by-first不返回任何内容。在Lisp书中,作者没有使用defstruct,所以我必须需要做一些稍微不同的事情?

(defun按名字选择(名字)
  (如果没有则删除
    #'(lambda(员工)
        (等于(getf员工:名字)名字))
    *emp-db*))

(首先选择“史蒂夫”)

完整的程序:

(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")

Rai*_*wig 5

有一些基本的错误/问题。但只需进行两个小更改,我们就可以让您的示例在 Common Lisp 中运行。

  • Emacs Lisp 的 Common Lisp 兼容包并不是真正的 Common Lisp。通常最好使用真正的 Common Lisp 实现。Emacs Lisp 缺乏一些难以模拟以使其与 Common Lisp 兼容的基本功能 - 例如词法闭包(更新 2014,最新版本的 GNU Emacs 现在也支持词法闭包)。

  • 小改动:我更改了您的示例,以便数据库不再包含史蒂夫·乔布斯两次,而是包含史蒂夫·乔布斯和史蒂夫·鲍尔默。

现在,我们需要更改什么才能使其在 Common Lisp 中运行?

  • (getf employee:first-name) 实际上应该是 (employee-first-name employee) 。DEFSTRUCT 宏自动生成这些访问器函数。在 Common Lisp 中,您无法使用 GETF 访问实际结构的字段。

  • 您的数据库有两个名为 STEVE(符号)的对象,但您正在搜索名称“steve”(字符串)。(等于'steve“steve”)是错误的。一般来说,符号不等于字符串。因此,您应该使用 (select-by-first '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))
Run Code Online (Sandbox Code Playgroud)