EDIT: The solution is to replace the ‘(1) with (list 1) in the first (let…) form. This is because I was trying to modify literal data. Thanks for the help! (I would give upvotes, but apparently you need 15 reputation…)
This is my first post on this site.
I was solving some Project Euler problems today and I came across some unexpected list sorting behavior (well, at least to me) in Common Lisp:
I have a function that finds all of the proper divisors of a number x:
(defun divisors (x)
"Finds all of the proper divisors of x."
(let ((sq (sqrt x)) (divs '(1)))
(when (integerp sq) (push sq divs))
(loop for i from 2 to (1- (floor sq)) do
(let ((div (/ x i)))
(when (integerp div)
(push i divs)
(push div divs))))
divs))
This function works great. For example:
(divisors 100)
==> (20 5 25 4 50 2 10 1)
The problem arises whenever I try to sort the resulting list:
(sort (divisors 100) #'<)
==> (1 2 4 5 10 20 25 50)
Well, that worked fine. But what happens when I call divisors again?
(divisors 100)
==> (20 5 25 4 50 2 10 1 2 4 5 10 20 25 50)
What? Maybe if I try a different number…
(divisors 33)
==> (11 3 1 2 4 5 10 20 25 50)
The divisors from previous queries are persistent after I sort the resulting list. If I recompile the function, I get no errors until I sort the resulting list again. I am assuming I have messed up somewhere in the function definition, but I am pretty new to Lisp and I cannot find the error. Could it be a problem with the nested (let…) forms?
Thanks in advance!
Frequently asked.
You’ve modified literal data. You need to cons up new data. Use the function LIST or the function to make a copy.