It may be worth noting that while the return value of range is wrapped in
lazy-seq and thus isn't itself a clojure.lang.IChunkedSeq, what you get
when you realize it is indeed chunked:

(contains? (ancestors (class (seq (range 128)))) clojure.lang.IChunkedSeq)
true

It doesn't implement c.l.IReduce, but clojure.core.protocols/InternalReduce
has an implementation for c.l.IChunkedSeq. At least transduce should be
able to take advantage of the InternalReduce implementation (via
CollReduce). transduce could be used for short-circuiting search with
(reduced …), so it might be a legitimate contender here.

Cheers,
Michał


On 2 April 2015 at 15:38, Tassilo Horn <t...@gnu.org> wrote:

> Alex Miller <a...@puredanger.com> writes:
>
> Hi Alex,
>
> > If you're going to use expanding transformations and not realize all of
> the
> > results then I think sequences are likely a better choice for you.
>
> Ok, I see.
>
> >> However, at least I had expected that in the case where all elements
> >> are realized the transducer version should have been faster than the
> >> traditional version which also needs to fully realize all
> >> intermediate lazy seqs.  Why is it still three times slower?
> >
> > I think my main suggestion here is that you are using a non-reducible
> > source (range) throughout these timings, so transducers have no
> > leverage on the input side. CLJ-1515 will make range reducible and
> > should help a lot on this particular example.
>
> Well, even if I revamp the (admittedly contrieved) example to have
> reducible vectors as source and also intermediates
>
>   (let [v (vec (range 0 1000))
>         vs (zipmap (range 0 1000)
>                    (for [i (range 0 1000)]
>                      (vec (range i 1000))))]
>     (time (dorun (sequence (comp (mapcat (fn [i] (vs i)))
>                                  (mapcat (fn [i] (vs i))))
>                            v))))
>
> it still takes 18 seconds instead of 21 with lazy seqs produced by
> range, or just 7 seconds with normal lazy seq functions.
>
> In my real scenario, I think there's also no IReduces paths because the
> mapcat functions either return normal lazy seqs or Java Collections
> (which are not actually clojure collections).  But usually, the
> transformations are not so freaking expanding as the example above.  I
> benchmarked a bit, and there sometimes using transducers is faster and
> sometimes it is not.  So I've made than configurable (with normal lazy
> seqs as default) so users can benchmark and then decide, and I don't
> need to choose for them. :-)
>
> Oh, and actually *you* have made that possible by making me aware of
>
>   (sequence (comp xform*) start-coll)
>
> is almost identical to
>
>   (->> start-coll xform*)
>
> that is, when my macro computes xforms as if they were meant for
> transducing, I can also use them "traditionally" with ->>.
>
> Until now, I've newer used ->> but before I had implemented the
> expansion for transducers, I used a for with gensyms for intermediates
> like:
>
>   (for [G__1 start-coll
>         G__2 (xform1 G__1)
>         G__3 (xform2 G__2)]
>     G__3)
>
> That's pretty much different to generate.  But since the xforms for
> transducers and ->> are the same, switching between lazy seq fns and
> transducers is just changing how start-coll and xforms are composed.
> Awesome!
>
> >> So my conclusion is that you cannot use transducers as a kind of
> >> drop-in replacement of traditional sequence manipulation functions.
> >> They pay off only when you can make very strong assumptions about the
> >> sizes and compututation costs of intermediate collections, and I
> >> think you cannot do that in general.  Or well, maybe you can when you
> >> program an application but you almost certainly cannot when you
> >> program a library and thus have no clue about how that's gonna be
> >> used by users.
> >
> > Transducers make different trade offs than sequences and there will
> > always be cases where one or the other is a better choice.  I really
> > appreciate this thread as highlighting some of the nuances.
>
> Yes, thanks a lot for your patience.  I appreciate that very much.
>
> > Transducers break transformations into three parts - source iteration,
> > composed transforms, and output collection.  In the case of reducible
> > inputs, multiple transforms, and full realization, transducers can be
> > much faster.  If not all of those are in play, then the results are
> > more subtle.  One thing I've found in perf testing a lot of stuff is
> > that chunked sequences continually surprise me at how fast they can
> > be.
>
> Then maybe I should experiment with chunged seqs.
>
> Bye,
> Tassilo
>
> --
> 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.
>

-- 
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.

Reply via email to