LISP函数影响其他函数



我注意到,当我调用fillBoard函数时,它似乎可以工作,因为它填充了传递给它的列表,但它有一个非常奇怪的副作用。不知怎么的,一旦fillBoard被调用,clearBoard函数将只返回由fillBoard返回的列表。另外,如果我再次调用fillBoard,它将继续更新clearBoard中返回的值。

据我所知,每次调用list变量都应该有一个新的实例,所以我不知道它是如何被修改的,也不知道它是如何存储一个新值的。

我将fillBoard传递一个空列表,例如((0 0 0 0)(0 0 0 0)(0 0 0 0)(0 0 0 0)),它将返回一个列表,例如((1 2 3 0)(0 6 0 0)(0 0 0 0)(0 0 0 0)),这就是clearBoard返回的内容。

(defun fillBoard (list)
   (let ((numVals (+ 4 (random 3)))
         (rand 0)
     (val1 0)
     (val2 0))
     (dotimes (x numVals)
     (setf val1 (random 3))
     (setf val2 (random 3))
     (setf rand (nth val1 (nth val2 soln)))
     (prin1 rand)
     (write-line " ")

     (if (= (nth val1 (nth val2 list)) 0)
     (setf (nth val1 (nth val2 list)) rand)))
      list))

(defun clearboard ()
   (let (( list '((0 0 0 0) (0 0 0 0) (0 0 0 0) (0 0 0 0))))
    list))

编辑:我似乎通过clearBoard传递一个列表,然后将其直接设置为空白板,而不是一个局部变量,然后返回,从而缓解了这个问题。然而,我仍然很好奇在最初的问题中发生了什么

返回结果的平等性

函数始终返回相同的文本列表。它是嵌入到代码中的数据。不要修改。

CL-USER 4 > (eq (clearboard) (clearboard))
T

EQ返回T,因为两个列表中的第一个cons实际上是相同的cons。

分配新的列表

clearboard中使用COPY-TREE来创建一个新分配的列表列表,而不是一遍又一遍地返回相同的文字列表:

(defun clearboard ()
  (copy-tree '((0 0 0 0)
               (0 0 0 0)
               (0 0 0 0)
               (0 0 0 0))))

CL-USER 5 > (eq (clearboard) (clearboard))
NIL

不要修改文字数据

文本数据在这里是一个数据列表,它嵌入在代码中。不要修改你的代码

clearboard返回的列表被定义为一个常量结构。当你在fillBoard中修改它时,你不是在修改一个副本,而是在修改结构本身。用

代替生成board
(loop repeat 4 collect (make-list 4 :initial-element 0))

相关内容

最新更新