Discussion:
Should core.async channels be deferrable?
Malcolm Sparks
2015-04-25 18:59:43 UTC
Permalink
I'm just wondering why manifold.deferred contains this logic :-

(utils/when-core-async
(extend-protocol Deferrable

clojure.core.async.impl.channels.ManyToManyChannel
(to-deferred [ch]
(let [d (deferred)]
(a/take! ch
(fn [msg]
(if (instance? Throwable msg)
(error! d msg)
(success! d msg))))
d))))


I find I'm having to wrap a core.async channel in a record in order for it
to return one in a d/chain function. That's OK, but I just wondered what
the rationale of making a core.async channel satisfy Deferrable. Is there
some interaction between d/chain and core.async channels here?

Thanks,

Malcolm
--
You received this message because you are subscribed to the Google Groups "Aleph" group.
To unsubscribe from this group and stop receiving emails from it, send an email to aleph-lib+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Zach Tellman
2015-04-25 19:10:16 UTC
Permalink
The basic rationale is that core.async treats channels as representing both
unbounded streams and single asynchronous values (this is explicit now that
there are promise-channels, but it's always been the convention). The
notion was to allow core.async channels to be used inside of a 'let-flow'
context, among others.

I assume this is causing issues for you where you mean channel-as-stream
and it's being interpreted as channel-as-value? One thing you can do is
call `->source` on it before passing it into `chain`, but there's always
going to be the risk of that sort of ambiguity. I'm open to the idea of
forcing people to be explicit and call `(take! (->source chan))` if this is
hurting more than it helps.

Zach
Post by Malcolm Sparks
I'm just wondering why manifold.deferred contains this logic :-
(utils/when-core-async
(extend-protocol Deferrable
clojure.core.async.impl.channels.ManyToManyChannel
(to-deferred [ch]
(let [d (deferred)]
(a/take! ch
(fn [msg]
(if (instance? Throwable msg)
(error! d msg)
(success! d msg))))
d))))
I find I'm having to wrap a core.async channel in a record in order for it
to return one in a d/chain function. That's OK, but I just wondered what
the rationale of making a core.async channel satisfy Deferrable. Is there
some interaction between d/chain and core.async channels here?
Thanks,
Malcolm
--
You received this message because you are subscribed to the Google Groups "Aleph" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Aleph" group.
To unsubscribe from this group and stop receiving emails from it, send an email to aleph-lib+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Malcolm Sparks
2015-04-26 13:24:21 UTC
Permalink
Hi Zach,

Your explanation makes perfect sense. That's also the convention when using
core.async go blocks (which return a channel which receives the result of
the go block). I understand it now, and agree the current implementation is
the right one.

Yes, in my case I wanted channel-as-stream. I've tried using `->source` and
it works for my case, so I've been able to remove the ugly hack of using
record wrappers.

Thanks a lot for your help.

Malcolm
Post by Zach Tellman
The basic rationale is that core.async treats channels as representing
both unbounded streams and single asynchronous values (this is explicit now
that there are promise-channels, but it's always been the convention). The
notion was to allow core.async channels to be used inside of a 'let-flow'
context, among others.
I assume this is causing issues for you where you mean channel-as-stream
and it's being interpreted as channel-as-value? One thing you can do is
call `->source` on it before passing it into `chain`, but there's always
going to be the risk of that sort of ambiguity. I'm open to the idea of
forcing people to be explicit and call `(take! (->source chan))` if this is
hurting more than it helps.
Zach
Post by Malcolm Sparks
I'm just wondering why manifold.deferred contains this logic :-
(utils/when-core-async
(extend-protocol Deferrable
clojure.core.async.impl.channels.ManyToManyChannel
(to-deferred [ch]
(let [d (deferred)]
(a/take! ch
(fn [msg]
(if (instance? Throwable msg)
(error! d msg)
(success! d msg))))
d))))
I find I'm having to wrap a core.async channel in a record in order for
it to return one in a d/chain function. That's OK, but I just wondered
what the rationale of making a core.async channel satisfy Deferrable. Is
there some interaction between d/chain and core.async channels here?
Thanks,
Malcolm
--
You received this message because you are subscribed to the Google Groups "Aleph" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Aleph" group.
To unsubscribe from this group and stop receiving emails from it, send an email to aleph-lib+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...