You need to use a buffer to defer calls to the reduced function (defn drop-last [n coll] (reducer coll (fn [f1] (let [buffer (atom clojure.lang.PersistentQueue/EMPTY)] (fn self ([] (f1)) ([ret x] (let [b (swap! buffer conj x)] (if (<= (count @buffer) n) ret (do (swap! buffer pop) (f1 ret (peek b)))))))))))
An array or a ring buffer should be used instead of the atom and persistent queue combo to reduce allocation. take-last is harder because you can't know when the reduction is over when using #'reducer, so you have to implement CollReduce yourself: (defn take-last [n coll] (reify clojure.core.protocols.CollReduce (coll-reduce [this f1] (clojure.core.protocols/coll-reduce this f1 (f1))) (coll-reduce [_ f1 init] (clojure.core.protocols/coll-reduce (clojure.core.protocols/coll-reduce coll (fn [q x] (let [q (conj q x)] (if (<= (count q) n) q (pop q)))) clojure.lang.PersistentQueue/EMPTY) f1 init)))) again, use of a mutable array/buffer would be preferable. hth, Christophe On Thu, Aug 8, 2013 at 1:00 PM, Jozef Wagner <jozef.wag...@gmail.com> wrote: > Is it possible to implement efficient butlast (and drop-last, take-last) > with reducers? The only solution I can think of needs additional reduce to > compute count, which may often be undesirable. > > Or is it OK to say that reducers are not designed for such cases? > > JW > > -- > -- > 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/groups/opt_out. > > > -- On Clojure http://clj-me.cgrand.net/ Clojure Programming http://clojurebook.com Training, Consulting & Contracting http://lambdanext.eu/ -- -- 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/groups/opt_out.