I think the difficulty here is that Chord has a bidirectional channel,
where putting and taking operate on different "streams" inside the channel.
(Internally, Chord is actually using a different channel for reads and
writes. It constructs the "joined" channel using chord.channels/bidi-ch)
I don't think this was envisioned as a proper way to use channels. I think
they were envisioned as a queue, and queues hold values, not communication
streams. When you put onto a channel, it contains what you put until you
take it off. (Note that channels with attached transducers must be buffered
because it needs a place to hold the result of the reduction step.) A Chord
channel isn't like this: when you put on it, the value is gone, and
different values from some other place appear when you take from it. The
more usual solution is to use a pair of channels.
map<, map>, etc happened to work because they always put/take a value
unchanged in the opposite direction onto the transformed channel.
I suspect the core developers were only using map>, map< et al in pipelines
(where transducers are fine) and not realizing people were using them in a
way that relied on the other direction being pass-through.
You will always need either a pair of channels to undo the unification done
by Chord, or you will need to implement a channel (using reify and the
WritePort and ReadPort protocols) where take and put mean different things
and you can attach a transducer independently to each. Something like that
would probably not make it in to core because it encourages the use of
Chord-style "multistream" channels.
You could try something like this:
(defn eduction> [xform ch]
(let [in-stream (chan 1 xform)
out-stream (chan)]
(pipe in-stream ch)
(pipe ch out-stream)
(chord.channels/bidi-ch in-stream out-stream)))
Of course it would be more efficient to use reify and implement the channel
interfaces directly, like map> does, but with transducer semantics for f
(including the finalize arity and when the f is called).
On Friday, February 12, 2016 at 1:41:20 PM UTC-6, James Reeves wrote:
>
> I currently have some core.async code that looks like:
>
> (map< :foo ch)
>
> However, map< and map> are now deprecated, with the suggestion to use
> transducers instead. Unfortunately it's not obvious how to go about that.
>
> At first I thought that I could use a pipe and a new channel:
>
> (pipe ch (chan 1 (map :foo)))
>
> But there's no distinction between channel input and output here. This
> matters because I'm using a bidirectional channel from Chord
> <https://github.com/jarohen/chord>.
>
> I'm thinking that it would be nice to have some functions like:
>
> (eduction< ch xform)
> (eduction> ch xform)
> (eduction ch xform)
>
> So I could write something like:
>
> (eduction< ch (map :foo))
>
> Have I missed anything? Is there some equivalent to this functionality
> already in core.async that I haven't noticed?
>
> - James
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.