Lisp 通过名称访问结构实例

Lisp 通过名称访问结构实例,lisp,common-lisp,Lisp,Common Lisp,我试图通过另一个结构实例或其名称访问结构实例的字段。诚然,这听起来非常令人困惑,我举了一个非常复杂的例子: (defstruct author (name nil) (books '()) (years '())) (defstruct book (name nil) (author '()) (copy-sold '())) (defparameter hitchikers-guide (make-book :name "Hitchikers-Guide"

我试图通过另一个结构实例或其名称访问结构实例的字段。诚然,这听起来非常令人困惑,我举了一个非常复杂的例子:

(defstruct author
  (name nil)
  (books '())
  (years '()))

(defstruct book
  (name nil)
  (author '())
  (copy-sold '()))

(defparameter hitchikers-guide
  (make-book :name "Hitchikers-Guide"
             :author '(douglas-adams)
             :copy-sold '(a lot)))

(defparameter douglas-adams
  (make-author :name "Douglas Adams"
               :books '(Hitchikers-guide restaurant life-and-universe fish)
               :years '(too few)))

(defparameter authors
  '(douglas-adams pterry))
我有《希奇客指南》。如果我想查找其作者的所有书籍,我可以输入REPL作者书籍道格拉斯·亚当斯,我会得到他所有书籍的列表。但是如果我进去

作者书籍第一本书作者希奇克斯指南

作者书籍第一作者

我收到错误消息:

DOUGLAS-ADAMS的值不是预期的类型

是我做错了,还是没有办法以这种方式访问这些字段?

您的变量authors包含符号,而不是authors

试一试

相反,如果,当然,翼翅已经被定义了

同样,书的作者希奇克斯指南是一个符号列表,而不是作者

您需要使用来获取相应的作者。

您的变量authors包含符号,而不是作者

试一试

相反,如果,当然,翼翅已经被定义了

同样,书的作者希奇克斯指南是一个符号列表,而不是作者


您需要使用来获取相应的作者。

如果您希望通过符号作为其标识符来查找对象,则需要为此使用数据结构

简单版本是在包中使用符号

(defun find-object (name)
  (symbol-value name))

(defun intern-object (object name)
  (setf (symbol-value name) object))
但您也可以使用哈希表:

(defvar *my-objects* (make-hash-table))

(defun find-object (name)
  (gethash name *my-objects*))

(defun intern-object (object name)
  (setf (gethash name *my-objects*) object))

如果希望通过符号作为标识符查找对象,则需要为此使用数据结构

简单版本是在包中使用符号

(defun find-object (name)
  (symbol-value name))

(defun intern-object (object name)
  (setf (symbol-value name) object))
但您也可以使用哈希表:

(defvar *my-objects* (make-hash-table))

(defun find-object (name)
  (gethash name *my-objects*))

(defun intern-object (object name)
  (setf (gethash name *my-objects*) object))

谁先来——作者还是书

;; first the author
(defstruct (author :conc-name make-author-internal)
  (name nil)
  (books '())
  (years '()))

(defun make-author (name years)
  (make-author-internal :name name :books '() :years years))

(defun author-add-book (author book)
  (setf (author-books author)
        (cons book (author-books author))))

;; now the book, requires an author (assumes one, if >1, use a list)
(defstruct (book :conc-name make-book-internal)
  (name nil)
  (author nil)
  (copy-sold '()))

(defun make-book (name author copy-sold)
  (let ((book (make-book-internal :name name :author author ...)))
    (author-add-book author book)
    book))

 ;; ...

 (defparameter douglas-adams
   (make-author "Douglas Adams" ...))

 (defparameter hitchikers-guide
   (make-book "Hitchikers-Guide" douglas-adams ...))

谁先来——作者还是书

;; first the author
(defstruct (author :conc-name make-author-internal)
  (name nil)
  (books '())
  (years '()))

(defun make-author (name years)
  (make-author-internal :name name :books '() :years years))

(defun author-add-book (author book)
  (setf (author-books author)
        (cons book (author-books author))))

;; now the book, requires an author (assumes one, if >1, use a list)
(defstruct (book :conc-name make-book-internal)
  (name nil)
  (author nil)
  (copy-sold '()))

(defun make-book (name author copy-sold)
  (let ((book (make-book-internal :name name :author author ...)))
    (author-add-book author book)
    book))

 ;; ...

 (defparameter douglas-adams
   (make-author "Douglas Adams" ...))

 (defparameter hitchikers-guide
   (make-book "Hitchikers-Guide" douglas-adams ...))

请注意,符号值仅在这种情况下有效,因为变量被声明为特殊变量,因为它们是用defparameter定义的。在这种情况下,执行defparameter的作者列出douglas adams Ptery是可能的,因为douglas adams和大概的Ptery已经定义。请注意,符号值仅在这种情况下有效,因为变量声明为特殊变量,因为它们是用defparameter定义的。在这种情况下,仅因为已经定义了douglas adams和大概的Ptery,所以可以使用defparameter作者列表douglas adams Ptery。在稍旧但仍然合法的样式中,您还可以使用已知键将对象隐藏在符号的属性列表中。然后您可以使用编写和检索它,例如,get'douglas adams'author将返回douglas adams的author对象。讨论给定类型的指示符也是一种很好的做法,尽管不是通用的。例如,字符串指示符是一个字符、字符串或符号,公共Lisp中大多数与字符串相关的函数都接受字符串指示符,而不仅仅是字符串。您可以将作者指示符定义为作者或符号,并让与作者相关的函数通过将符号静默映射到其名称的作者来获取作者指示符。在稍旧但仍然合法的样式中,您还可以使用已知键将对象隐藏在符号的属性列表中。然后您可以使用编写和检索它,例如,get'douglas adams'author将返回douglas adams的author对象。讨论给定类型的指示符也是一种很好的做法,尽管不是通用的。例如,字符串指示符是一个字符、字符串或符号,公共Lisp中大多数与字符串相关的函数都接受字符串指示符,而不仅仅是字符串。您可以将作者指示符定义为作者或符号,并让与作者相关的函数通过将符号无声地映射到其命名的作者来获取作者指示符。