将defstruct数据库与remove-if-not一起使用 [英] Using a defstruct database with remove-if-not

查看:85
本文介绍了将defstruct数据库与remove-if-not一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过添加以下示例来适应 defstruct 示例本书中所述的 select-功能:实用常见的Lisp 。我正在使用Common Lisp软件包在Emacs中运行代码。 首先选择不会返回任何内容。在Lisp书中,作者没有使用defstruct,所以我必须做一些稍微不同的事情?

I'm trying to adapt this defstruct example by adding the select- functions described in the book: Practical Common Lisp. I'm running the code in Emacs using the Common Lisp package. The select-by-first does not return anything. In the Lisp book, the author does not use defstruct so I must need to do something slightly different?


(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中工作。

There are a few basic mistakes/problems. But with only two small changes we can get your example to work in Common Lisp.


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

  • Emacs Lisp's compatibility package for Common Lisp is not really a Common Lisp. It is generally preferable to use a real Common Lisp implementation. Emacs Lisp lacks a few basic things that are hard to emulate to make it compatible with Common Lisp - for example lexical closures (update 2014, the latest version of GNU Emacs now also supports lexical closures).

微小变化:我更改了您的示例,以使数据库不会两次包含史蒂夫·乔布斯,而是史蒂夫·乔布斯和史蒂夫·鲍尔默。

Minor change: I changed your example so that the database does not contain Steve Jobs twice, but Steve Jobs and Steve Ballmer.

现在,我们需要更改使其在Common Lisp中起作用吗?

Now, what would we need to change to make it work in Common Lisp?


  • (getf雇员:名)应该确实是(雇员名雇员)。 DEFSTRUCT宏会自动生成这些访问器函数。在Common Lisp中,您不能使用GETF访问实际结构的字段。

  • (getf employee :first-name) should really be (employee-first-name employee) . The DEFSTRUCT macro generates these accessor functions automatically. In Common Lisp you can't use GETF to access the fields of real structures.

您的数据库有两个名称为STEVE(符号)的对象,但是您正在搜索名称 steve(字符串)。 (等于'steve steve)为假。通常,符号不等于字符串。因此,您应该使用(按优先顺序选择史蒂夫)进行搜索。

Your database has two objects with the name STEVE (a symbol), but you are searching for the name "steve" (a string). (equal 'steve "steve") is false. In general a symbol is not EQUAL to a string. So you should search with (select-by-first 'steve).

在LispWorks中,然后:

In LispWorks then:

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

这篇关于将defstruct数据库与remove-if-not一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆