Почему сшитые дефекты вызывают переполнение стека?

Играя с графиками, я получил странную ошибку, которую я не совсем понял. Код ниже воспроизводит проблему.

;; Define struct to store a node with links to other nodes.
(defstruct node properties links)

;; Make two nodes
(setf a (make-node :properties '(:name a))
      b (make-node :properties '(:name b)))

;; Create link from b to a. This works fine...
(push b (node-links a))

;; ... but this crosslink makes lisp chase its own tail for a while and then crash with a stack overflow.
(push a (node-links b))

Я получил тот же результат с SBCL и Clozure. настройка *print-length* до управляемой стоимости не сработало.

Поэтому у меня следующие вопросы: почему этот код не создает такой же бесконечный цикл печати, как круговой список (т. Е. Переполнение стека и его нельзя остановить с помощью Ctrl-C). Любой вклад приветствуется.

Спасибо Пауло

1 ответ

Решение

*print-length* контролирует количество элементов в списке. Ты ищешь *print-level*, Это прекрасно работает для меня.

(let ((*print-level* 3))
  (format t "~W~%" a))
;; Output: #S(NODE :PROPERTIES (:NAME A)
;;  :LINKS (#S(NODE :PROPERTIES # :LINKS #)))

В качестве альтернативы, вы можете использовать *print-circle* обнаруживать циклы и печатать их еще лучше.

(let ((*print-circle* t))
  (format t "~W~%" a))
;; Output: #1=#S(NODE :PROPERTIES (:NAME A)
;;  :LINKS (#S(NODE :PROPERTIES (:NAME B) :LINKS (#1#))))

Здесь он фактически обнаруживает цикл и печатает #1#, ссылка на #1= чтобы показать, что это тот же объект.

Другие вопросы по тегам