我在使用Lisp时遇到了一些麻烦。我正在尝试做的是跟踪数字在x个列表中出现的次数。但是,一遍又一遍地运行它,lisp不会重新创建变量,而是使用上次调用函数时的结束值。所以我想知道如何才能超越let的“约束力”?
所以,我有一些这样的列表
(((8 7) (3)) ((8 3) (2)) ((7 3) (6)) ((7 2) (8)) ((6 7) (4 1))
((6 6) (4 1)) ((6 2) (2)) ((5 6) (3)) ((5 3) (8 3)) ((4 6) (4))
((4 4) (6)) ((4 1) (7)) ((3 7) (5 3)) ((3 4) (1)) ((3 3) (3)) ((3 1) (9))
((2 7) (7)) ((2 5) (2)) ((2 2) (5 2)) ((1 7) (1)) ((1 6) (6 1))
((1 1) (2 1)) ((1 0) (3)) ((0 7) (8 1)) ((0 5) (6)) ((0 3) (9 6))
((0 1) (1)))
然后我正在调用这样的函数,(这里声明var似乎没有做任何事情,通过初始函数调用)...我想从let中得到某种绑定。
(defun counter (possibleValues)
(let ((var '(0 0 0 0 0 0 0 0 0 0)))
(loop for i from 0 to (list-length possibleValues) do
(loop for j in (cdr (nth i possibleValues)) do
(loop for k in j do
(incf (nth k var)))))
var))
所以我可以通过该函数运行我的列表并获得类似
的内容(0 8 5 6 3 2 5 2 3 2)
每个位置都指的是列表中的数字。所以值8将指的是在所有列表中找到1的次数(我只考虑第二个列表)。现在问题....运行两次......
(0 16 10 12 6 4 10 4 6 4)
我之前使用的是关联列表,但在尝试解决这个问题并保持简单时,我现在正在使用列表。我想我的另一个问题是,如何动态创建关联列表元素?我不喜欢这样宣称'var',但我只是试图绕过'让'。我对'setq'或'setf'也没有太多运气......
提前感谢您的帮助!
答案 0 :(得分:4)
将VAR的初始化表单更改为创建新列表的表达式,例如(make-list 10 :initial-element 0)
甚至(list 0 0 0 0 0 0 0 0 0 0)
。
基本上,如果您有意修改它们,请不要使用引用的对象,因为如果您这样做,后果是不确定的。实际上,评估该函数定义会对此发出警告:
; in: LAMBDA NIL ; (INCF (NTH K VAR)) ; --> LET* ; ==> ; (SB-KERNEL:%SETNTH #:TMP5 #:TMP4 #:NEW3) ; ; caught WARNING: ; Destructive function SB-KERNEL:%SETNTH called on constant data. ; See also: ; The ANSI Standard, Special Operator QUOTE ; The ANSI Standard, Section 3.2.2.3 ; ; compilation unit finished ; caught 1 WARNING condition