Lisp воссоздает временную переменную - PullRequest
2 голосов
/ 13 ноября 2010

У меня проблемы с Лиспом. То, что я пытаюсь сделать, это отслеживать количество раз, которое число появляется в х количество списков. Тем не менее, повторяя это снова и снова, 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' ....

Заранее спасибо за помощь!

1 Ответ

4 голосов
/ 13 ноября 2010

Измените форму инициализации 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)
; 
<b>; 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
;</b> 
; compilation unit finished
;   caught 1 WARNING condition
...