在处理个人项目时,我发现闭包的行为似乎不一致。
以下代码中的想法是通过一个接一个地检查它们来找到几个数字(1,3,2,5,4)中的最大值。最大值显然是5.下面的代码看起来很复杂,因为它们是从更复杂的案例中得出的最小例子。
代码1,包含普通数字 - >它有效
(defun look-for-maximum-1 ()
(labels ((test-successive-values-with-function (f)
(let ((z 0))
(setf z 1)
(funcall f z)
(setf z 3)
(funcall f z)
(setf z 2)
(funcall f z)
(setf z 5)
(funcall f z)
(setf z 4)
(funcall f z))))
(let ((maximum -1))
(test-successive-values-with-function
;; function to check if a given number is the new maximum:
(lambda (x)
(format t "~&Inspecting ~S whereas maximum is ~S" x maximum)
(when (> x maximum)
(format t "~&Maximum was: ~S" maximum)
(setf maximum x)
(format t "~&Maximum is now: ~S" maximum))))
(format t "~&Final maximum: ~S" maximum))))
对(look-for-maximum-1)
的调用带来以下输出:
检查1,而最大值为-1
最大值为:-1
现在最大值:1
检查3,而最大值为1
最大值为:1
现在最大值:3
检查2,而最大值为3
检查5,而最大值为3
最大值为:3
现在最大值:5
检查4,而最大值为5
最终最高限额:5
此输出正确:程序逐步找到最大值(即5)。
代码2 =与单元素列表中封装的数字相同 - >它不起作用
(defun look-for-maximum-2 ()
(labels ((compare-car (list1 list2)
"Returns true if and only if the car of list1 is > than car of list2"
(> (car list1) (car list2)))
(test-successive-values-with-function (f)
(let ((z '(0)))
(setf (car z) 1)
(funcall f z)
(setf (car z) 3)
(funcall f z)
(setf (car z) 2)
(funcall f z)
(setf (car z) 5)
(funcall f z)
(setf (car z) 4)
(funcall f z))))
(let ((maximum '(-1)))
(test-successive-values-with-function
;; function to check if a given number is the new maximum:
(lambda (x)
(format t "~&Inspecting ~S whereas maximum is ~S" x maximum)
(when (compare-car x maximum)
(format t "~&Maximum was: ~S" maximum)
(setf maximum x)
(format t "~&Maximum is now: ~S" maximum))))
(format t "~&Final maximum: ~S" maximum))))
对(look-for-maximum-2)
的调用带来以下输出:
检查(1)而最大值是(-1)
最大值为:( - 1)
现在最大值:(1)
检查(3)而最大值为(3)
检查(2)而最大值为(2)
检查(5)而最大值为(5)
检查(4)而最大值为(4)
最终最大值:(4)
不正确。该程序似乎失去了最大值,而它在闭合范围内。最大值似乎系统地设置为被检查数字的值,而不应该是这样。
对于上述奇怪的行为有什么想法?
代码经过测试: - 通过Emacs + Slime的CLISP - SBCL通过Emacs +史莱姆 - Common Lisp on line:https://www.tutorialspoint.com/execute_lisp_online.php