2012-02-18 2 views
3

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

;;Data structure for a person 

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

Я тогда procede инстанцировать несколько человеко объектов:

(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 и print-function, но я не могу понять, как правильно печатать мои объекты. Используя что-то вроде:

(print person-a) 

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

ответ

6

Общий lisp имеет переменную, которая управляет печатью рекурсивных структур: *print-circle*. В вашем Lisp оно может быть ложным (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).

НТН,

Kyle

+0

Это очень полезно. У меня есть вопросы о вашем форматировании. Можете ли вы объяснить три строки форматирования? Мне также любопытно, почему каждый объект объекта печатает дважды. – Isthan

+0

форма (формат nil «...» ...) печатает на консоль, подобную тому, как печатаются и принц. формат является общим эквивалентом printf/sprintf lisp. Мой код печатает каждого человека с форматом, а затем снова с печатью, чтобы показать, что печать рекурсивной структуры завершается успешно. –

Смежные вопросы