Search code examples
clojure

Why can't this recur function be defined?


This works fine:

(defn fact [x]
  (loop [n x prod 1]
    (if (= 1 n)
      prod
      (recur (dec n) (* prod n)))))

and this one can even be evaluated as a symbol:

(defn fact2 []
  (loop [prod [1 2 3]]
    (if (empty? prod)
      prod
      (recur (rest prod) (* prod 2)))))

What's wrong with the second one?


Solution

  • This is the exception thrown on evaluating the second expression:

    Execution error (IllegalArgumentException) at user/fact2 (test.clj:3).
    Mismatched argument count to recur, expected: 1 args, got: 2
    

    The loop binding in fact2 has only one variable (which is called prod), however, the recur call would pass 2 values. You can not use the single variable prod to hold both the product (a number) and the list of numbers (a collection).

    The correct definition would look something like this:

    (defn fact2 []
      (loop [n [1 2 3] prod 1]
        (if (empty? n)
          prod
          (recur (rest n) (* prod 2)))))