按名称访问结构实例

时间:2013-06-26 16:31:43

标签: lisp common-lisp

我正在尝试通过另一个结构实例或其名称访问结构实例的字段。由于这听起来非常令人困惑,我有一个(非常构造的)例子:

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

我有实例hitchikers-guide。如果我想查找其作者的所有书籍,我可以输入REPL (author-books douglas-adams),我会得到他所有书籍的清单。但是,如果我输入

(author-books (first (book-author hitchikers-guide)))

(author-books (first authors))

我收到错误消息:

  

值DOUGLAS-ADAMS不是预期类型AUTHOR。

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

3 个答案:

答案 0 :(得分:5)

您的变量authors包含symbol s,而不是author s。

尝试

(defparameter authors (list douglas-adams pterry))

相反(如果已经定义了cource,pterry)。

同样,(book-author hitchikers-guide)symbol的列表,而不是author

您需要使用symbol-value来获取相应的author

答案 1 :(得分:4)

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

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

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

答案 2 :(得分:1)

首先是作者还是书?

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