8

I'm just learning to use lazy sequences in Clojure, and I'm not sure what I'm doing wrong in the following code:

(defn sum [seqn]
  (reduce + seqn))

(defn fib
  ([] (concat [0 1] (fib 0 1)))
  ([a b] (lazy-seq (cons (+ a b) (fib b (+ a b))))))

(defn up-to [n seqn]
  (filter (fn [x] (< x n)) seqn))

(sum (up-to 100 (fib))) => ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)

The numbers being summed shouldn't be larger than 100, so what is causing the integer overflow?

Chetan
  • 46,743
  • 31
  • 106
  • 145

2 Answers2

5

starting with clojure 1.3.0 numbers don't auto-promote to bigInt/bigDecimal.

to fix this use +' instead

your 100th fibinachi number is too large for an integer

user> (nth (fib) 100)
354224848179261915075N
Arthur Ulfeldt
  • 90,827
  • 27
  • 201
  • 284
5

Filtering an infinite seq produces an infinite seq and reducing over this causes filter to keep looking for another matching item even after the predicate stops returning true.

Replace filter with take-while. The infinite sequence generated by (fib) will cause filter to run forever, but before that it will break due to the ArithmeticException you're experiencing. take-while will stop further evaluation of the list after the (fn [x] (< x n)) predicate evaluates to false.

(defn up-to [n seqn]
  (take-while (fn [x] (< x n)) seqn))

(sum (up-to 100 (fib))) ;; => 232
Jan
  • 11,636
  • 38
  • 47
  • How does filter evaluate the whole list? I thought it was supposed to produce a lazy seq? – Alex Jun 25 '12 at 21:34
  • 3
    Never mind, I see... it's not the filter itself. Filtering an infinite seq produces an infinite seq, and reducing over this causes filter to keep looking for another matching item even after the predicate stops returning true. – Alex Jun 25 '12 at 21:39
  • Got it, seems like Alex's reasoning is more accurate than the answers. Please update the answer so that I can mark it as correct. – Chetan Jun 26 '12 at 00:46
  • Chetan, done. Does it cut it now? @Alex, thanks for your comments. – Jan Jun 26 '12 at 01:13
  • A good way to bring home the difference between take-while and filter. – Geoffrey Aug 03 '15 at 10:16