3 ms·
(defn infinite-series [] (let [x (atom 0)] (repeatedly (fn [] (swap! x inc))))) (take 10 (map #(* 10 %) (infinite-series))) The arguments of 'take
by yason 14y ago
(defn infinite-series []
(let [x (atom 0)]
(repeatedly (fn [] (swap! x inc)))))
(take 10 (map #(* 10 %) (infinite-series)))
The arguments of 'take' and 'map' are eagerly evaluated. The sequence returned by 'infinite-series' is immutable and infinite and lazy, and as returned it actually gets passed directly to the 'map' function which actually operates on it. Finally, we use 'take' to extract the first ten items and thanks to the data structure being lazy, this will actually limit the execution so that only ten items are ever generated and multiplied by 10.
The code would look conceptually the same in Haskell but if the 10 in 'take' was a variable and could occasionally be 0, in Clojure you can be sure that a debug (println) places in the 'infinite-series' function would actually get executed. Haskell would probably defer the execution forever since "take 0" is a no-op. Yet Clojure doesn't generate or multiply anything if we called (take 0 ...).