I have this Sundaram's sieve to generate prime numbers up to limit in Common Lisp.
(defun sundaram-sieve (limit)
(let ((numbers (range 3 (+ limit 1) 2))
(half (/ limit 2))
(start 4))
(dolist (step (range 3 (+ limit 1) 2))
(dolist (i (range start half step))
(setf (nth (- i 1) numbers) 0))
(setq start (+ start (* 2 (+ step 1))))
(if (> start half)
(return (cons 2 (remove-if #'zerop numbers)))))))
Here range is defined as:
(defun range (min max step)
(loop for n from min below max by step
collect n))
How can i make the code above more functional and idiomatic? The use of setq and setf bothers me, not to mention that it takes 10 seconds to calculate with limit equal 100000, when the equivalent code in Python runs almost instantly.