我在以下代码中出现堆栈溢出,然后在SBCL中尝试了一下并成功了。想知道是什么造成了那里的差异。
特别是:虽然我确实计划在某个时候移至SBCL,但可以在CLISP中使用它吗?
(defvar *objs* nil) ; [1]
(defun parents (obj) (gethash :parents obj))
(defun obj (&rest parents) ; [2]
(let ((obj (make-hash-table)))
(push obj *objs*)
(setf (parents obj) parents)
obj))
(defun (setf parents) (val obj) ; [3]
(prog1 (setf (gethash :parents obj) val)
(make-precedence obj)))
(defun make-precedence (obj) ; [4]
(setf (gethash :preclist obj) (precedence obj))
(dolist (x *objs*)
(if (member obj (gethash :preclist x))
(setf (gethash :preclist x) (precedence x)))))
(defun precedence (obj) ; [5]
(delete-duplicates (traverse obj)))
(defun traverse (x) ; [6]
(cons x (mapcan #'traverse (gethash :parents x))))
;; [1] We'll store a list of objects we create in *obj*.
;; [2] Function to create an object, called like (setf scoundrel (obj)).
;; [3] Set an objects (multiple) parents & rebuild precedence list for all affected objs.
;; [4] Rebuild precedence list for obj, then for all affected objs.
;; [5] Returns a list of object and all its ancestors in precedence order as we define it.
;; (Can read it like (-> obj traverse delete-duplicates) if it helps)
;; [6] Cons an object to all its parents recursively; depth first search.
;; I pulled this out of labels in precedence above it for clarity & testability.
;; Source: PG's ANSI Common Lisp, Chapter 17, "Example: Objects".
Run Code Online (Sandbox Code Playgroud)
示例-SBCL
(setf scoundrel (obj))
; #<HASH-TABLE :TEST EQL :COUNT 2 {1001A01893}>
(setf sc2 (obj scoundrel))
; #<HASH-TABLE :TEST EQL :COUNT 2 {1001A1F153}>
*objs*
; (#<HASH-TABLE :TEST EQL :COUNT 2 {1001A1F153}>
; #<HASH-TABLE :TEST EQL :COUNT 2 {1001A01893}>)
(parents scoundrel)
; NIL
; T
(parents sc2)
; (#<HASH-TABLE :TEST EQL :COUNT 2 {1001A01893}>)
; T
Run Code Online (Sandbox Code Playgroud)
示例-GNU CLISP
(setf scoundrel (obj))
;; - Lisp stack overflow. RESET
*objs*
;; - Lisp stack overflow. RESET
Run Code Online (Sandbox Code Playgroud)
值得一提的是,我还没有研究lisp 的双重解释和编译性质。到目前为止,我只是将其用作解释语言。通过将上述功能粘贴到剪辑副本中。
因此,我怀疑编译所有这些功能可能是要考虑的一件事。我注意到我们可以compile和compile-file,我看不出它编译所有用户定义的函数,虽然运营商。
默认情况下,GNU CLISP打印哈希表的内容。在您的情况下,它包含圆形结构。
*PRINT-CIRCLE*为T 均可启用打印圆形结构而不会引起堆栈溢出。> (setq *print-circle* t)
T
> *objs*
(#1=#S(HASH-TABLE :TEST FASTHASH-EQL (:PRECLIST . (#1#)) (:PARENTS . NIL)))
Run Code Online (Sandbox Code Playgroud)
*PRINT-ARRAY*和设置*PRINT-READABLY*为NIL,以禁止打印哈希表的内容。> (setq *print-circle* nil *print-array* nil *print-readably* nil)
NIL
> *objs*
(#<HASH-TABLE :TEST FASTHASH-EQL :COUNT 2 #x000335098D40>)
Run Code Online (Sandbox Code Playgroud)