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

标签 elisp common-lisp

我正在尝试调整此 defstruct例如,添加本书中描述的 select- 函数: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")

最佳答案

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

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

  • 小改动:我更改了您的示例,这样数据库就不再包含 Steve Jobs 两次,而是包含 Steve Jobs 和 Steve Ballmer。

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

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

  • 您的数据库有两个名为 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))

关于elisp - 使用带有 remove-if-not 的 defstruct 数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2182210/

相关文章:

emacs - 像TextMate一样在打开/关闭标签中包装选择?

emacs - 我如何应用新的 Emacs C 样式来重新格式化我的所有源文件?

tree - 打开音乐 : L-System tree generation using lisp

windows - 如何使用 erlang.el 设置 Erlang + Emacs?

function - Emacs:钩子(Hook)如何工作?

lisp - 将 Lisp 代码形成任务——与展平列表方法相关

lisp - "Hot"Common LISP 中的调试和交换

lisp - Common Lisp程序错误

lisp - 总是喜欢标签而不是车队?

python - Emacs 中的 Rope 和 Yasnippet