Hi Leon, I think this is an edge case related to how varargs functions are implemented in Clojure.
The varargs arity of `max` is implemented with `reduce1`: core.clj line 1088 <https://github.com/clojure/clojure/blob/36d665793b43f62cfd22354aced4c6892088abd6/src/clj/clojure/core.clj#L1088> `reduce1` is a simplified implementation of "reduce" defined early in clojure.core before the optimized reduction protocols have been loaded: core.clj line 894 <https://github.com/clojure/clojure/blob/36d665793b43f62cfd22354aced4c6892088abd6/src/clj/clojure/core.clj#L894>. `reduce1` is implemented in terms of lazy sequences, with support for chunking. So `apply max` defaults to using chunked lazy sequence operations. `map` and `range` both return chunked sequences. `eduction` returns an Iterable, so when you `apply max` on it, it turns the Iterable into a Seq, but it's not a chunked seq. Therefore, it's slightly slower than `apply max` on a chunked seq. In this case, to ensure you're using the fast-path internal reduce over ` eduction`, you can use `reduce` directly: (reduce max 0 (eduction (map inc) (range 100000))) You must provide an init value because `eduction` does not assume the "init with first element" behavior of sequences. This version, in my informal benchmarking, is the fastest. Lots of functions in clojure.core use `reduce1` in their varargs implementation. Perhaps they could be changed to use the optimized `reduce`, but this might add a lot of repeated definitions as clojure.core is bootstrapping itself. I'm not sure. In general, I would not assume that `eduction` is automatically faster than lazy sequences. It will be faster only in the cases where it can use the optimized reduction protocols such as InternalReduce. If the optimized path isn't available, many operations will fall back to lazy sequences for backwards-compatibility. I would suggest using `eduction` only when you *know* you're going to consume the result with `reduce` or `transduce`. As always, test first, and profilers are your friend. :) –S On Saturday, July 18, 2015 at 9:11:45 AM UTC-4, Leon Grapenthin wrote: > > My understanding was that if I pass an eduction to a process using reduce, > I can save the computer time and space because the per step overhead of > lazy sequences is gone and also the entire sequence does not have to reside > in memory at once. > > When I time the difference between (apply max (map inc (range 100000))) > and (apply max (eduction (map inc) (range 100000))), the lazy-seq variant > wins. > > I'd like to understand why, and when eductions should be used instead. > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.