Thanks so much for your input Alex! It was a very helpful confirmation of 
the key conclusions arrived at in this thread, and I appreciate the 
additional elaborations you gave, especially the insight you passed on 
about the stateful transducers using `ArrayList`. I'm glad that I wasn't 
the only one wondering about the apparent lack of parity between its 
unsynchronized mutability and the volatile boxes used for e.g. 
`map-indexed` and others.

As an aside about the stateful `take` transducer, Tesser uses the 
equivalent of one but skirts the issue by not guaranteeing that the first n 
items of the collection will be returned, but rather, n items of the 
collection in no particular order and starting at no particular index. This 
is achievable without Tesser by simply replacing the `volatile` in the 
`core/take` transducer with an `atom` and using it with `fold`. But yes, 
`take`'s contract is broken with this and so still follows the rule of 
thumb you established that `fold` can't use stateful transducers (at least, 
not without weird things like reordering of the indices in `map-indexed` 
and so on).

That's interesting that `fold` can use transducers directly! I haven't 
tried that yet — I've just been wrapping them in an `r/folder`.

On Sunday, April 9, 2017 at 10:22:13 PM UTC-4, Alex Miller wrote:
>
> Hey all, just catching up on this thread after the weekend. Rich and I 
> discussed the thread safety aspects of transducers last fall and the 
> intention is that transducers are expected to only be used in a single 
> thread at a time, but that thread can change throughout the life of the 
> transducing process (for example when a go block is passed over threads in 
> a pool in core.async). While transducing processes may provide locking to 
> cover the visibility of state updates in a stateful transducer, transducers 
> should still use stateful constructs that ensure visibility (by using 
> volatile, atoms, etc).
>
> The major transducing processes provided in core are transduce, into, 
> sequence, eduction, and core.async. All but core.async are single-threaded. 
> core.async channel transducers may occur on many threads due to interaction 
> with the go processing threads, but never happen on more than one thread at 
> a time. These operations are covered by the channel lock which should 
> guarantee visibility. Transducers used within a go block (via something 
> like transduce or into) occur eagerly and don't incur any switch in threads 
> so just fall back to the same old expectations of single-threaded use and 
> visibility.
>
> Note that there are a couple of stateful transducers that use ArrayList 
> (partition-by and partition-all). From my last conversation with Rich, he 
> said those should really be changed to protect themselves better with 
> volatile or something else. I thought I wrote up a ticket for this but 
> looks like maybe I didn't, so I will take care of that. 
>
> Reducer fold is interesting in that each "bucket" is reduced via its 
> reduce function, which can actually use a transducer (since that produces a 
> reduce function), however, it can't be a stateful transducer (something 
> like take, etc).
>
> Hope that helps with respect to intent.
>
>

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