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