EDIT: Transducers are actually not safe in `fold` contexts as I thought: (let [f (fn [i x] (println (str "i " i " " (Thread/currentThread))) (flush) x) r-map-indexed #(r/folder %2 (map-indexed %1))] (->> [6 7 8 9 10] (r-map-indexed f) (r/fold 1 (fn ([] (vector)) ([x] x) ([a b] (into a b))) conj)))
Produces: i 0 Thread[ForkJoinPool-1-worker-2,5,main] i 2 Thread[ForkJoinPool-1-worker-1,5,main] i 3 Thread[ForkJoinPool-1-worker-1,5,main] i 4 Thread[ForkJoinPool-1-worker-1,5,main] i 1 Thread[ForkJoinPool-1-worker-3,5,main] So you would have to be careful to e.g. create different `map-indexed` transducers for single-threaded (e.g. `unsynchronized-mutable` box) and multi-threaded (e.g. `atom` box) contexts. On Sunday, April 9, 2017 at 2:10:06 AM UTC-4, Alexander Gunnarson wrote: > > I was wondering the same thing, shintotomoe. This thread > <https://groups.google.com/forum/#!topic/clojure/CjxK7xEsOKQ> talks about > it as well. I think it's safe to assume that since `ArrayList` uses > unsynchronized mutability internally (a quick review of the GrepCode > entry for `ArrayList` confirms this > <http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/ArrayList.java>), > > then we can rest assured that a `volatile` box as opposed to a totally > unsynchronized mutable variable is unnecessary, even in the context of > `fold`. After all, `reduce` (and by extension, `transduce`) is only ever > going to be single-threaded unless the data structure in question > unexpectedly implements a multithreaded reduce, which should never happen > (and if it does, you likely have bigger problems). To be honest, I'm not > sure why `volatile` is used in transducers instead of e.g. an > `unsynchronized-mutable` box. There may be a good reason, but I'm not > seeing it immediately. I'd love to learn. > > On Thursday, January 1, 2015 at 10:36:13 PM UTC-5, shintotomoe wrote: >> >> Thank you for the superfast response. I take it implementing your own >> transducing process is not something you would usually do unless you have a >> unique use case (my own use case being already implemented by chan taking a >> transducer). >> >> Still, I was wondering about the use of ArrayList in partition-all, and >> the recommendation to use volatiles inside transducers, which seem at odds. >> It seems we don't need to implement transducers in a thread-safe way. Is >> that correct? >> >> On Friday, January 2, 2015 12:58:51 PM UTC+11, tbc++ wrote: >>> >>> Core.async already has pipeline, pipeline-blocking and pipeline-async. >>> In addition you can use a transducer inside a channel. Use those instead. >>> >>> Timothy >>> >>> On Thu, Jan 1, 2015 at 6:55 PM, shintotomoe <tste...@atlassian.com> >>> wrote: >>> >>>> I was wondering how to apply a transducer inside a go process. What >>>> I've so far is the following >>>> >>>> (defn pipe-xform [in-ch out-ch xform] >>>> (let [tr >>>> (let [tr (xform (fn >>>> ([result] result) >>>> ([result input] (conj! result input))))] >>>> (fn >>>> ([] (locking tr (persistent! (tr (transient []))))) >>>> ([input] (locking tr (persistent! (tr (transient []) input >>>> ))))))] >>>> (go-loop [] >>>> (if-some [value (<! in-ch)] >>>> (do (doseq [v (tr value)] >>>> (>! out-ch v)) >>>> (recur)) >>>> (do (doseq [v (tr)] >>>> (>! out-ch v)) >>>> (close! out-ch)))))) >>>> >>>> Now, I could just do >>>> >>>> (let [xf-ch (chan 1 xform)] >>>> (pipe in-ch xf-ch) >>>> (pipe xf-ch out-ch) >>>> >>>> >>>> Or just redesign my code so that I can create in-ch or out-ch with the >>>> transducer directly, but I was wondering whether there are any obvious >>>> flaws with the pipe-xform implementation. >>>> >>>> In particular, I was wondering about the locking. At first I was under >>>> the impression that transducers are thread-safe due to the use of >>>> volatiles, but looking at the partition-all transducer, which uses an >>>> ArrayList for its state, It appears that's not the case. >>>> >>>> Any feedback greatly appreciated. >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "Clojure" group. >>>> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> >>> >>> -- >>> “One of the main causes of the fall of the Roman Empire was that–lacking >>> zero–they had no way to indicate successful termination of their C >>> programs.” >>> (Robert Firth) >>> >> -- 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.