transducer not applied with unbuffered channels
Description
Environment
Activity

Alex MillerNovember 5, 2015 at 3:17 AM
After talking to Rich, it is considered an error to created a fixed buffer of size 0 and that should throw. The ticket ASYNC-143 covers that check.
On the last question, a transducer needs to be (potentially) be able to produce multiple values with something like a mapcat transducer. Without a buffer, there is no place for those buffers to go, so an unbuffered channel is insufficient.

importNovember 4, 2015 at 11:10 PM
Comment made by: alex.nixon
I vote to reopen this.
As a user this feels like a very subtle bug - the docstring says "if a transducer is supplied, a buffer must be specified". In your example you have specified a buffer – one of size zero – and so it's very surprising when you find out (at some later stage in your program) that your transducer was silently ignored. If a fixed buffer of size zero is not a valid thing to construct then I would expect (buffer 0) to throw an IllegalArgumentException or similar.
And philosophically I don't understand why the combination of an unbuffered channel and a transducer should be forbidden. What's the argument here?

Alex MillerAugust 18, 2015 at 2:17 PM
I'm a dope and unbuffered channels (or 0-sized fixed buffer) channels do not support transducers per the chan docstring.

Alex MillerAugust 17, 2015 at 11:13 PM
I suspect the problem is here:
https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/channels.clj#L115-L133
where a take can't get a value from the buffer (there is none) and instead satisfies itself by matching up directly with a put. In this case, add! is never called so the transducer is not applied.
In the case of an expanding transducer, a buffer is needed at this point where none exists.
Details
Assignee
Alex MillerAlex MillerReporter
Alex MillerAlex MillerApproval
TriagedPriority
Critical
Details
Details
Assignee

Reporter

Found this while testing some stuff on ASYNC-124.
Cause: For an unbuffered channel, a take will try to pair up with a put, in which case the two are satisfied directly without ever involving the buffer (since there isn't one). Because of this, add! is never called and the xf will not be applied. The example above uses an expanding transducer, but problem exists for any transducer and could perhaps happen even on buffered channels?
Approach: one approach would be to not satisfy the put unless there were enough pending takes to satisfy all the transduced values, which seems consistent with an unbuffered channel.