0
votes

I am trying to read numbers from input and printing them back in Clojure till I read the number 42. A really basic thing to make sure I know how to read input. Taken from codechef

I have written this program. Might not be good clojure.

(defn universe
  []
  (let [num (line-seq (java.io.BufferedReader. *in*))]
    (if (not= num 42)
      (do
        (println num)
        (recur (universe))
        )
      )
    )
  )

My understanding is that line-seq lazily evaluates from whatever reader is given. In this case the standard input.

So I have let it be num. Then if num is not 42 I print it and then recursively call universe. But it throws exception

Mismatched argument count to recur, expected: 0 args, got: 1,

I have seen an example and recur does take an argument. Looking at the official documentation I couldn't see the syntax for this. So why am I getting this error?

1

1 Answers

4
votes

recur does not take the name of the location to recur to. Instead the recur special form jumps back up to the closest function or loop expression, whichever is closer. It then passes it different arguments. This lets you go through the same block of code repeatedly as you work through the data, and there is no function call overhead.

In your case it's recurring up to the function call:

(defn universe [] ...

and trying to pass it an argument, which fails because universe, the function, does not accept any arguments. perhaps you intended to put a loop expression around the if?

user> (defn universe
        []
        (let [numbers (line-seq (java.io.BufferedReader. *in*))]
          (loop [numbers numbers]
            (let [num (first numbers)]
              (if (not= (Integer/parseInt num) 42)
                (do
                  (println num)
                  (recur (rest numbers))))))))
#'user/universe
user> (universe)
3   ;; typed 3 
nil ;; typed 42

or where you intending to recur back to the top of the function, in which case just call (recur) instead of (recur universe)