Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure map function being eager?

According to Mark's awesome tutorial page, "The map function applies a given function that takes one parameter to each item in a collection, returning a lazy sequence of the results".

Yet when I do the following:

(def input-message-list (range 100 126))

(defn test-123 [in]
  (println "doing " in)
  (str "out " in))

(def output-test (map
                   test-123
                   input-message-list))

(first output-test)

, in the REPL I get the println side effects for the full range, not just the first element!

What is going on here people?

like image 212
YMA Avatar asked Feb 28 '11 09:02

YMA


2 Answers

Already answered in here:

as really 32 elements are evaluated at a time

Your range has less than 32 elements.

like image 129
Serabe Avatar answered Oct 23 '22 07:10

Serabe


This is part of the chunked sequences which really helps the performance of the "map over lazy seq" pattern that is so ubiquitous in Clojure. This way your mapping function gets a lot more successive calls and makes it's way into the JVM hotspot compiler's fast path a lot faster. When Rich demoed this in San Francisco in 2008 it was amazing to see these two chunks of code run at the same speed:

(reduce + (map inc (range 10000)))

and

(loop [i 0 sum 0]
   (recur (inc i) (+ sum i)))

Now you can write idomatic clojure and get full speed. if it gets to be a problem then you can turn it off here

like image 3
Arthur Ulfeldt Avatar answered Oct 23 '22 07:10

Arthur Ulfeldt