2

我在使用 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',但我只是想暂时避开 'let'。我对'setq'或'setf'也没有太多运气......

在此先感谢您的帮助!

4

1 回答 1

4

将 VAR 的初始化形式更改为创建新列表的表达式,例如(make-list 10 :initial-element 0)or (list 0 0 0 0 0 0 0 0 0 0)

基本上,如果您打算修改引用的对象,则永远不要使用它们,因为如果这样做,后果是不确定的。事实上,评估该函数定义会发出警告:

; 在: 兰姆达无
; (INCF (NTH K VAR))
; --> 让*
; ==>
; (SB-内核:%SETNTH #:TMP5 #:TMP4 #:NEW3)
;
; 抓住警告:
; 破坏性函数 SB-KERNEL:%SETNTH 调用常量数据。
; 也可以看看:
; ANSI 标准,特殊运算符 QUOTE
; ANSI 标准,第 3.2.2.3 节
; 
; 编译单元完成
; 捕获 1 个警告条件
于 2010-11-12T22:33:05.163 回答