Search code examples
lispcommon-lisp

Lisp collect random items if they are even


Coming from other programming languages, I recently found lisp and am amazed. Reading through the loop macro, I wanted to generate a list with random numbers with a condition (let's just pretend the numbers should be even). So I came up with this:

(defun some-test (range)
  (loop repeat range
        with item = (random 1000)
        if (evenp item)
        collect item))

However, this gives me the same random number range times. What am I doing wrong here? Apparently, item is only evaluated once and not in every iteration.


Solution

  • with evaluates the expression before the loop starts. If you want to compute an intermediate value on each iteration, you need to replace it with for:

    (defun some-test (range)
      (loop for item = (random 1000)
            repeat range
            if (evenp item)
            collect item))
    

    Running (some-test 5) then returns up to 5 even numbers, for example:

    CL-USER> (some-test 5)
    (758 750 300)
    CL-USER> (some-test 5)
    (954)