Recursion SBCL中的递归

Recursion SBCL中的递归,recursion,common-lisp,tail-recursion,sbcl,Recursion,Common Lisp,Tail Recursion,Sbcl,我对SBCL(linux上)有一个问题,可能与尾部递归有关(我并不完全确定这是什么)。这次我添加了代码(看起来很长,但那是因为我把它全部拉伸了) 交易是我有一个函数“compare pstructs”,它比较两个结构。但是,这些结构可能具有与组件相同的结构列表。当然,这需要一个递归的解决方案 当上述函数需要比较这些PST结构的列表时,将调用第二个函数“compare parses”。当然,compare parses函数必须再次调用compare pstructs函数来比较各个pstructs

我对SBCL(linux上)有一个问题,可能与尾部递归有关(我并不完全确定这是什么)。这次我添加了代码(看起来很长,但那是因为我把它全部拉伸了)

交易是我有一个函数“compare pstructs”,它比较两个结构。但是,这些结构可能具有与组件相同的结构列表。当然,这需要一个递归的解决方案

当上述函数需要比较这些PST结构的列表时,将调用第二个函数“compare parses”。当然,compare parses函数必须再次调用compare pstructs函数来比较各个pstructs

因此,它应该在构建堆栈帧的这些函数之间来回跳转,然后在发现单个PST结构匹配或不匹配时将它们弹出,并在发现整个解析匹配或不匹配时执行相同的操作

实际发生的是,第一次弹出堆栈帧时,不再发生递归调用。更奇怪的是,沿着pstructs列表(在compare parses函数中)遍历的循环继续迭代,只执行compare pstructs函数回调下面的代码

我将尝试将这些函数组合成一个函数,但我仍然想知道为什么它不能作为两个函数工作

下面是代码和日志。谢谢大家注意

-托德

(destruct pstruct
句法信息;列表
从属关系;;更多PST结构的列表
)
(定义比较分析(p1t p2t)
(def参数idx 0)
(DEF参数最大idx(长度p1t))
如果它们的长度不一样,所有的赌注都输了。
(若否)
(相等
(长度p1t)
(长度p2t)
)
)
(从比较返回解析为零)
)
(环路
(在比较PST结构之前打印“idx:”)
(打印idx)
(如果
(空(比较PST结构(第n个idx p1t)(第n个idx p2t)))
(从比较返回解析为零)
)
(setf idx(1+idx))
(打印“将一个添加到idx:”)
(打印idx)
(如果(>=idx最大idx)
(返回)
) 
)
(从比较分析T返回)
)
(取消比较PST结构(p1 p2)
(打印“P1”)
(打印p1)
(打印“P2”)
(打印p2)
(如果(不等于(pstruct语法信息p1)(pstruct语法信息p2)))
(从比较PST结构返回NIL)
)
(如有)(及
(null(pstruct从属项p1))
(null(pstruct从属项p2))
)
(从比较pstructs T返回)
)
(如有)(及
(非(null(pstruct从属项p1)))
(非(null(pstruct从属项p2)))
)
(从比较pstructs返回)
(比较解析)
(pstruct从属项p1)(pstruct从属项p2)
)
)
)
;如果一个或另一个(不是两个)受抚养人为零,则返回零。
(从比较PST结构返回NIL)
)
;; 测试数据的两个结构(请注意,其中一个结构中有一个“X”
使两者不同。
(d)参数x2
#S(p结构
:syntarchy-INFO(“Sfin”)
:受抚养人(P结构
:syntarchy-INFO(“Ext”“NP”“Pron\u Pron”“Pers\u Pron”“S”
“Sin1”“第一”“Sin”“NomC”)
:受抚养人(P结构
:syntarchy-INFO(“PRON”“PRON_PRON”
“Pers_PRON”“Sin1”“S”
“Sin1”“1st”“Sin”
“NomC”)
:家属(无)
#S(PSTRUCT
:syntarchy-INFO(“Plu”“Sin2”“Sin3”“Sin1”“Pres”“V”
“Trans_V”“TransComp_V”“Intrans_V”
“Ditrans_V”“Inf”)
:家属(无)
#S(PSTRUCT
:语法信息(“DNI”)
:家属(无)
(2)参数y2
#S(p结构
:syntarchy-INFO(“Sfin”)
:受抚养人(P结构
:syntarchy-INFO(“Ext”“NP”“Pron\u Pron”“Pers\u Pron”“S”
“Sin1”“第一”“Sin”“NomC”)
:受抚养人(P结构
:syntarchy-INFO(“PRON”“PRON_PRON”
“Pers_PRON”“Sin1”“S”
“Sin1”“1st”“Sin”
“NomC”)
:家属(无)
#S(PSTRUCT
:syntarchy-INFO(“Plu”“Sin2”“Sin3”“Sin1”“Pres”“V”
“Trans_V”“TransComp_V”“Intrans_V”

“Ditrans_V”“Inf”“X”);不要在函数内部使用
defparmeter
。它定义了一个全局变量,这会在
COMPARE-PARSES
中打乱逻辑,因为递归调用将使用相同的变量

您的代码是相当单一的Lisp。您不应该像那样使用
IF
s和
RETURN-FROM
。请将函数构造为单个表达式

(defstruct pstruct
  ;; Instead of comments to say what type these are,
  ;; you could use code to tell it.
  (syntactic-info nil :type list)
  (dependents nil :type list))

;; Since the functions call each other, it's better to declare
;; their ftypes beforehand.
(declaim (ftype (function (list list) boolean) compare-parses)
         (ftype (function (pstruct pstruct) boolean) pstruct=))

(defun compare-parses (p1t p2t)
  (and (= (length p1t)
          (length p2t))
       (every #'pstruct= p1t p2t)))

(defun pstruct= (p1 p2)
  (and (equal (pstruct-syntactic-info p1)
              (pstruct-syntactic-info p2))
       (compare-parses (pstruct-dependents p1)
                       (pstruct-dependents p2))))
Common Lisp还提供了一些调试工具,因此您不需要打印东西

如果您使用的是Emacs和Slime/Sly,那么也可以使用,以获得更好的界面


另请参见和Slime等价物。

不要在函数内部使用
DEFPARAMETER
。它定义了一个全局变量,这会在
COMPARE-PARSES
中打乱逻辑,因为递归调用将使用相同的变量

您的代码是相当单一的Lisp。您不应该像那样使用
IF
s和
RETURN-FROM
。请将函数构造为单个表达式

(defstruct pstruct
  ;; Instead of comments to say what type these are,
  ;; you could use code to tell it.
  (syntactic-info nil :type list)
  (dependents nil :type list))

;; Since the functions call each other, it's better to declare
;; their ftypes beforehand.
(declaim (ftype (function (list list) boolean) compare-parses)
         (ftype (function (pstruct pstruct) boolean) pstruct=))

(defun compare-parses (p1t p2t)
  (and (= (length p1t)
          (length p2t))
       (every #'pstruct= p1t p2t)))

(defun pstruct= (p1 p2)
  (and (equal (pstruct-syntactic-info p1)
              (pstruct-syntactic-info p2))
       (compare-parses (pstruct-dependents p1)
                       (pstruct-dependents p2))))
Common Lisp还提供了一些调试工具,因此您不需要打印东西

如果您使用的是Emacs和Slime/Sly,那么也可以使用,以获得更好的界面

CL-USER> (trace compare-parses pstruct=)
CL-USER> (pstruct= *x2* *y2*)
... Prints the trace ...
CL-USER> (untrace compare-parses pstruct=)