문제

I'm having a bit of trouble with Lisp. What i'm attempting to do, is keep track of the amount of times a number appears in x number of lists. However, running this over and over again, lisp isn't recreating the variable, but using the ending value from the last time I called the function. So I'm wondering how can I get past the 'binding' powers of let?

So, I've got some list like this

    (((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))) 

Then I'm calling some function like this, (declaring var here doesn't seem to do anything, past the initial function call)... I guess some kind of binding from 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))

So I can run my list through the function and get something like

(0 8 5 6 3 2 5 2 3 2)

Each position referring to the number found in the list. So the value 8 would refer to how many times 1 was found in all the lists (i'm considering the second list only). Now the problem.... run it twice and...

(0 16 10 12 6 4 10 4 6 4)

I was using an associative list earlier, but in trying to figure this out and keep things simple, i'm now using a list. I guess another question I have is, how can I create associative list elements on the fly? I don't like declaring 'var' like that, but I'm just trying to get around 'let' for the moment. I haven't had much luck with 'setq' or 'setf' either....

Thanks in advance for your help!

도움이 되었습니까?

해결책

Change the initialization form for VAR to be an expression that creates new lists, such as (make-list 10 :initial-element 0) or even (list 0 0 0 0 0 0 0 0 0 0).

Basically, do not ever use quoted objects if you have intentions on modifying them, as the consequences are undefined if you do. In fact, evaluating that function definition gives a warning about that:

; 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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top