【问题标题】:Lisp Stack overflow recursive functionLisp Stack溢出递归函数
【发布时间】:2016-12-07 20:11:59
【问题描述】:

我正在创建一个启发式函数,它返回它应该返回的内容,但也存在堆栈溢出问题,我不明白问题出在哪里。这是我创建的函数的代码:

(defun nextPositions (position)
  (let*((listaPosAdjacentes)
        (positionFinal position)
        (listaFinal NIL))
    (setf listaPosAdjacentes (possible-actions2))
    (dolist (posAdjacente listaPosAdjacentes)
      (setf positionFinal position)
      (setf positionFinal (list (+ (nth 0 positionFinal) (nth 0 posAdjacente))
                                (+ (nth 1 positionFinal) (nth 1 posAdjacente))))
      (push positionFinal listaFinal))
    listaFinal))

(defun push-unique (element lista)
  (let ((auxlist lista))
    (dolist (i lista)
      (if (and (equal (nth 0 i) (nth 0 element)) (equal (nth 1 i) (nth 1 element)))
          (return-from push-unique auxlist)))

    (push element auxlist)
    auxlist))

(defun recursive (track1 positionslist distance track)
  (let ((NextValidPositions NIL))
    (dolist (position positionslist)
      (if (equal (track-startpos track) position)
          (return-from recursive track1)
        (progn (dolist (i (nextPositions position))
                 (if (equal (nth (nth 1 i) (nth (nth 0 i) track1)) T)
                     (progn 
                       (setf NextValidPositions (push-unique i NextValidPositions))
                       (setf (nth (nth 1 i) (nth (nth 0 i) track1)) (+ 1 distance))))))))
    (recursive track1 NextValidPositions (+ 1 distance) track)))

(defun compute-heuristic(st)
  (let* ((track (state-track st))
         (distance 0)
         (track1Final nil)
         (track1heuristica (track-env track)))
    (dolist (position (track-endpositions track))
      (setf (nth (nth 1 position) (nth (nth 0 position) track1heuristica)) distance))
    (setf track1Final (recursive track1heuristica (track-endpositions track) distance track))
    (print track1Final)
    (return-from compute-heuristic track1Final)))

结果如下:

它返回的列表是它应该返回的,但我无法理解堆栈溢出问题。

代码是这样调用的:

  (format t "~&Exercise 3.1 - Heuristic~&")
  (with-open-file (str "out3.1.txt"
     :direction :input)
  (format t "~% Solution is correct? ~a~&" (equal (list (compute-heuristic (initial-state *t1*)) (compute-heuristic (make-state :pos '(1 6)  :track track)) (compute-heuristic (make-state :pos '(2 8)  :track track))) (read str))))

这是一个本地测试,此代码由我们的教授提供用于测试我们的代码,这就是我认为问题不存在的原因。

任何想法可能是什么问题? 谢谢。

【问题讨论】:

  • 在深入研究之前,您能告诉我们您是如何调用代码的吗?此外,一般调试提示:(跟踪)递归中涉及的全部或部分函数。
  • 仅供参考,有一个内置宏 PUSHNEW 就像你的 PUSH-UNIQUE
  • 我认为问题不在于您发布的代码。由于(print track1Final) 执行成功,问题发生在之后,所以它必须在调用compute-heuristic 的代码中。
  • P.S.请不要发布不必要的图片。从命令提示符复制并粘贴为文本。
  • 我用调用函数的代码编辑了帖子。并感谢您的提示。

标签: recursion lisp stack-overflow


【解决方案1】:

关于风格

通常代码写得不好,因为它使用了太多并不真正需要的控制结构和变量。

例子:

(defun push-unique (element lista)
  (let ((auxlist lista))
    (dolist (i lista)
      (if (and (equal (nth 0 i)
                      (nth 0 element))
               (equal (nth 1 i)
                      (nth 1 element)))
          (return-from push-unique auxlist)))
    (push element auxlist)
    auxlist))
  • 不必要的变量auxlist
  • 不需要dolist,使用member
  • 不需要return-from,只需返回值。在很多情况下,使用return-from 是一种代码味道,表示代码过于复杂。
  • 不需要push,只返回cons的结果

更好:

(defun push-unique (element list)
  (if (member element list
              :test (lambda (a b)
                      (and (equal (first a) (first b))
                           (equal (second a) (second b)))))
      list
      (cons element list)))

该功能已经存在

函数push-unique 已经存在于标准Common Lisp 中。它被称为adjoin

CL-USER 34 > (adjoin 1 '(2 3 4 1 3))
(2 3 4 1 3)

CL-USER 35 > (adjoin 1 '(2 3 4 3))
(1 2 3 4 3)

只需根据您的目的通过正确的测试功能...

(defun push-unique (element list)
  (adjoin element list
          :test (lambda (a b)
                  (and (equal (first a) (first b))
                       (equal (second a) (second b))))))

评论和文档

编写 cmets 和文档可能也是一个好主意。 否则必须猜测/推断这些函数的目的是什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多