Распечатать defstruct в Лиспе - PullRequest
       0

Распечатать defstruct в Лиспе

3 голосов
/ 18 февраля 2012

У меня есть очень простая структура данных, которую я определил в Лиспе:

;;Data structure for a person

(defstruct person
  (name nil)
  (age 0)
  (siblings nil :type list))   ;; Siblings is a list of person objects

Затем я приступаю к созданию нескольких объектов:

(setf person-a (make-person :name 'Tim :age 23))
(setf person-b (make-person :name 'Sally :age 21))
(setf person-c (make-person :name 'Louis :age 24))

Затем я связываю братьев и сестер (предположим, что они все братья и сестры друг друга):

(setf (person-siblings person-a) (list person-b person-c))
(setf (person-siblings person-b) (list person-a person-c))
(setf (person-siblings person-c) (list person-b person-a))

Как я могу затем распечатать информацию об объектах, которые я создал и модифицировал? Я рассмотрел параметры defstruct в отношении print-object и print-function, но я не могу понять, как правильно печатать мои объекты. Используя что-то вроде:

(print person-a)

отправляет мой интерпретатор ACL в бесконечный цикл.

1 Ответ

6 голосов
/ 18 февраля 2012

Common lisp имеет переменную, которая управляет печатью рекурсивных структур: *print-circle*. В вашем Лиспе он может быть ложным (nil) по умолчанию (как в SBCL и clisp - я не знаком с ACL), что, вероятно, вызывает бесконечный цикл. Если вы установите значение t, ваши структуры должны напечатать:

(setf *print-circle* t)

Я проверил это с помощью следующего файла:

(defstruct person
  (name nil)
  (age 0)
  (siblings nil :type list))

(setf person-a (make-person :name 'Tim :age 23))
(setf person-b (make-person :name 'Sally :age 21))
(setf person-c (make-person :name 'Louis :age 24))

(setf (person-siblings person-a) (list person-b person-c))
(setf (person-siblings person-b) (list person-a person-c))
(setf (person-siblings person-c) (list person-a person-b))

(setf *print-circle* t)
(format t "~a~&" person-a)
(format t "~a~&" person-b)
(format t "~a~&" person-c)

(print person-a)
(print person-b)
(print person-c)

Вот расшифровка стенограммы запуска этого кода:

> sbcl
This is SBCL 1.0.55, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (load "defstruct.lisp")

#1=#S(PERSON
        :NAME TIM
        :AGE 23
        :SIBLINGS (#2=#S(PERSON
                         :NAME SALLY
                         :AGE 21
                         :SIBLINGS (#1#
                                    #3=#S(PERSON
                                          :NAME LOUIS
                                          :AGE 24
                                          :SIBLINGS (#1# #2#))))
                   #3#))
#1=#S(PERSON
      :NAME SALLY
      :AGE 21
      :SIBLINGS (#2=#S(PERSON
                       :NAME TIM
                       :AGE 23
                       :SIBLINGS (#1#
                                  #3=#S(PERSON
                                        :NAME LOUIS
                                        :AGE 24
                                        :SIBLINGS (#2# #1#))))
                 #3#))
#1=#S(PERSON
      :NAME LOUIS
      :AGE 24
      :SIBLINGS (#2=#S(PERSON
                       :NAME TIM
                       :AGE 23
                       :SIBLINGS (#3=#S(PERSON
                                        :NAME SALLY
                                        :AGE 21
                                        :SIBLINGS (#2# #1#))
                                  #1#))
                 #3#))

#1=#S(PERSON
      :NAME TIM
      :AGE 23
      :SIBLINGS (#2=#S(PERSON
                       :NAME SALLY
                       :AGE 21
                       :SIBLINGS (#1#
                                  #3=#S(PERSON
                                        :NAME LOUIS
                                        :AGE 24
                                        :SIBLINGS (#1# #2#))))
                 #3#)) 
#1=#S(PERSON
      :NAME SALLY
      :AGE 21
      :SIBLINGS (#2=#S(PERSON
                       :NAME TIM
                       :AGE 23
                       :SIBLINGS (#1#
                                  #3=#S(PERSON
                                        :NAME LOUIS
                                        :AGE 24
                                        :SIBLINGS (#2# #1#))))
                 #3#)) 
#1=#S(PERSON
      :NAME LOUIS
      :AGE 24
      :SIBLINGS (#2=#S(PERSON
                       :NAME TIM
                       :AGE 23
                       :SIBLINGS (#3=#S(PERSON
                                        :NAME SALLY
                                        :AGE 21
                                        :SIBLINGS (#2# #1#))
                                  #1#))
                 #3#)) 
T
* (sb-ext:quit)

Если я оставлю *print-circle* nil, то получу ошибку переполнения стека (SB-KERNEL::CONTROL-STACK-EXHAUSTED в sbcl).

НТН,

Кайл

...