I have read the following document and the example, but still doesn't get what it really means. I understand alts!!, but not alt!!.Anybody show an example easy to understand?
https://clojure.github.io/core.async/#clojure.core.async/alt!!
I have also ready the following link
In Clojure (core.async) what's the difference between alts and alt?
update: The example is in the doc is:
(alt!
[c t] ([val ch] (foo ch val))
x ([v] v)
[[out val]] :wrote
:default 42)
for the second line of
[c t] ([val ch] (foo ch val))
channel-op of [c t] means a channel c and an value t: put value t on channel c. result-expr of ([val ch] (foo ch val)) means bidding [val ch] for the operation, but since it's a list, [val ch] should be evaluate as a function, and (foo ch val) will be as the parameter passed to function of [val ch]. but what does it mean for function of [val ch] with parameter of (foo ch val) ?
[c t] ([val ch] (foo ch val))
There are some cases where a list doesn't mean "evaluate as a function". For example:
(ns com.foo.bar
(:require …))
In the above code, there is no function called :require
being called.
Another example of lists being used for something other than function application is letfn
:
(letfn [(foo [x] (+ (bar 1) x))
(bar [x] (+ 2 x))]
(+ (foo 5) (bar 7)))
As you can see above, letfn
has two lists, one starting with the symbol foo
, and one starting with the symbol bar
, and neither of these lists is a traditional function call. Instead, letfn
is defining two new functions, one with the name foo
, and the other with the name bar
. The rest of the expression is treated as a "body" in which to use those functions.
but what does it mean for function of [val ch] with parameter of (foo ch val) ?
Similar to letfn
, alt
defines a value named val
and a channel named ch
, and then the rest of the expression ((foo ch val)
) is treated as a "body" in which to use those two names.
alt!/alt!!
:I find it easiest to think of alt!
and alt!!
as being somewhat like cond
, except instead of testing conditions to choose a body to execute, it waits on channels to choose a body to execute. Each clause consists of two parts, just like cond
– the first part (the "channel op") is used to specify a channel that alt!
should wait on, and the second part (the "result expr") specifies what should happen if that channel delivers a value first.
Since you probably want to access the value delivered by the channel or the channel itself when this happens, the result expr gives you the opportunity to bind both the value and the channel to symbols, and a body of code to execute with those bindings. Thus, the following clause…
[c t]
([val ch]
(foo ch val))
…means:
One of the channel operations that this call to
alt!
should block on is an attempt to take from either of two channels,c
ort
. If either of those send a value before any other channel op in this call toalt!
, then execute(foo ch val)
withval
bound to the value taken from the channel that first delivered a value, and withch
bound to the channel that deliveredval
(which will be eitherc
ort
).
and the following clause…
[[out input-val]]
([val ch]
(bar ch val))
…means:
One of the channel operations that this call to
alt!
should block on is an attempt to putinput-val
onto a channel calledout
. If that succeeds before any other channel op in this call toalt!
, then execute(bar ch val)
withval
bound toinput-val
andch
bound toout
(the channel that successfully received the value).
Altogether, these two clauses would be written as:
(alt!
[c t] ; "Takes" can be a single channel instead of vectors.
([val ch]
(foo ch val))
[[out input-val]] ; "Puts" must be nested vectors.
([val ch]
(bar ch val)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With