LIST vs TICK in a LET causing a global side-effect?!?
Posted: Mon Feb 20, 2012 4:58 pm
I am writing some numerical routines and trying to observe a strict functional approach. Today I got bitten by a bug I can't explain with my understanding of how LET, LIST and QUOTE work.
I had the following code (significantly simplified to show the bug without cluttering up with the actual purpose of the code)
It would run as I expected the first time invoked after compilation (SBCL 1.0.55):
Any further invocations would not however run properly:
When I changed the LET form to
The problem went away. Can someone explain to me how I am getting crosstalk between two separate invocations of the same function through a locally defined variable? I have verified that my (next-permutation) function is non-destructive, but even if it were how does the LET '(1 2 3 4... not reinitialize the same every time?.
I had the following code (significantly simplified to show the bug without cluttering up with the actual purpose of the code)
Code: Select all
(defun digit-magic ()
(let ((dig-list '(1 2 3 4 5 6 7 8 9))
(i 0))
(remove-if #'null
(loop until (or (> i 100000) (null dig-list)) do
(if (zerop (mod i 10000))
(progn (format t "~d: ~a~%" i dig-list)
(force-output)))
(setf i (1+ i))
(setf dig-list (next-permutation dig-list))))))
Code: Select all
CPE-PROJECT> (digit-magic)
0: (1 2 3 4 5 6 7 8 9)
10000: (1 3 9 8 4 6 7 2 5)
20000: (1 5 9 7 6 3 4 2 8)
30000: (1 7 9 6 2 3 4 5 8)
40000: (1 9 8 5 3 6 7 2 4)
50000: (2 3 9 5 7 4 6 1 8)
60000: (2 5 9 4 1 3 6 7 8)
70000: (2 7 9 3 4 6 8 1 5)
80000: (2 9 8 1 6 4 5 3 7)
90000: (3 2 9 1 4 5 6 7 8)
100000: (3 5 8 9 2 6 7 1 4)
NIL
Code: Select all
EULER-PROJECT> (digit-magic)
0: (1 2 3 4 5 6 7 9 9 8 6 9 9 8 6 9 9 7 6 8 8 7 5 7 9 9 8 5 9 9 8 5 9 9 7
5 8 8 7 5 6 9 9 8 5 9 9 8 5 9 9 6 5 8 8 6 5 6 9 9 7 5 9 9 7 5 9 9 6 5
7 7 6 5 6 8 8 7 5 8 8 7 5 8 8 6 5 7 7 6 4 6 7 9 9 8 6 9 9 8 6 9 9 7 6
8 8 7 4 7 9 9 8 4 9 9 8 4 9 9 7 4 8 8 7 4 6 9 9 8 4 9 9 8 4 9 9 6 4 8
8 6 4 6 9 9 7 4 9 9 7 4 9 9 6 4 7 7 6 4 6 8 8 7 4 8 8 7 4 8 8 6 4 7 7
6 4 5 7 9 9 8 5 9 9 8 5 9 9 7 5 8 8 7 4 7 9 9 8 4 9 9 8 4 9 9 7 4 8 8
7 4 5 9 9 8 4 9 9 8 4 9 9 5 4 8 8 5 4 5 9 9 7 4 9 9 7 4 9 9 5 4 7 7 5
4 5 8 8 7 4 8 8 7 4 8 8 5 4 7 7 5 4 .....lots more data
Code: Select all
(let ((dig-list (list 1 2 3 4 5 6 7 8 9))