Sorry, I just realized that you were referring to the exact same
examples Jay Fields uses...so you must already know about that article! ;-)
(2014/05/12 23:07), Dave Della Costa wrote:
>> The x is referring to the map that is to be
>> added in as a parameter, right?
>
> So, taking one example from James's code:
>
> (defn transparent-put [{:keys [channel buffer]} x]
> (go
> (>! channel x)
> (swap! buffer conj x)))
>
> The x is the second argument to the function--it's the message you put
> into the channel, in this case.
>
> The contrast with the let form you used as an example is that the let
> form is assigning the right value to the left destructuring form. But
> in the case of a function, the value that is passed in is what is
> getting destructured. Contrast this:
>
> (let [{:keys [a b]} {:a 1 :b 2}]
> (println "a: " a ", b: " b))
>
> with this:
>
> (defn destruct
> [{:keys [a b]}]
> (println "a: " a ", b: " b))
>
> (destruct {:a 1 :b 2})
>
> Does that help?
>
> If you haven't read this great article about destructuring by Jay Fields
> yet, I highly recommend you do:
>
> http://blog.jayfields.com/2010/07/clojure-destructuring.html
>
>> Like you said, I also feel like I'm *starting* to get it and it is
>> really exciting :) Thanks for your advice.
>
> Great! You're very welcome--good luck.
>
> DD
>
> (2014/05/12 21:43), gamma235 wrote:
>> Your description of what is going on with my macro was really helpful.
>> In my head I was imagining recursive evals running over the code, saying
>> first, then, etc. I didn't really think about compile time vs. run-time.
>>
>> I am impressed with James' code as well, but I am having trouble fully
>> understanding it and getting it to run. From the transparent put
>> definition, it doesn't seem like it is possible to pass a channel value
>> as a parameter in the call. The x is referring to the map that is to be
>> added in as a parameter, right? at least that is why I learned, when I
>> studied destructuring:
>>
>> (def point {:x 5 :y 7})
>>
>>
>>
>> (let [{:keys [x y]} point]
>> (println "x:" x "y:" y))
>>
>>
>>
>> => :x 5 :y 7
>>
>>
>> Does it work different different for defining function parameters? I
>> posted more under his comment above, please have a look.
>>
>> Like you said, I also feel like I'm *starting* to get it and it is
>> really exciting :) Thanks for your advice.
>>
>> Jesse
>>
>> On Monday, May 12, 2014 7:46:34 PM UTC+9, David Della Costa wrote:
>>
>> > to reason about and can be dangerous. I would suggest putting
>> > dynamically created channels in a collection inside an atom if you
>> > need to create them like this.
>>
>> P.S. I just read James's response and I see he said something similar
>> regarding this--it's better to structure this as a hash-map or other
>> data structure, and use an atom if it needs to be updated dynamically.
>> Notice that his code is far simpler and easier to reason about, and
>> avoids the use of macros.
>>
>> DD
>>
>> (2014/05/12 19:40), Dave Della Costa wrote:
>> >> I think I am confused about how to distinguish between a symbol
>> and a
>> >> variable, as I thought that the symbol being derefed pointed to the
>> >> atom that it was made to define when transparent-chan was called.
>> >
>> > I think it's not so much that, as being mistaken about what is
>> going at
>> > compile-time vs. run-time in your macros. Going back to your
>> original
>> > code, your log-name function is just fine:
>> >
>> > (defn log-name [ch] (symbol (str ch '-log)))
>> >
>> > It returns a symbol, which is what you want for the second arg to
>> def.
>> >
>> > However, keep in mind that this is going to return a list which will
>> > then get evaluated, but it will only be the last value returned
>> from 'do':
>> >
>> > (defmacro transparent-chan [ch]
>> > (do
>> > `(def ~ch (chan))
>> > `(def (log-name ~ch) (atom []))
>> > `(println "new transparent channel created!")))
>> >
>> > that is, a list like this:
>> >
>> > `(println "new transparent channel created!")
>> >
>> > ...which will then get evaluated at run-time. So your def calls will
>> > never run! If we know that we can adjust it--
>> >
>> > (defmacro transparent-chan [ch]
>> > `(do (def ~ch (async/chan))
>> > (def (log-name ~ch) (atom []))
>> > (println "new transparent channel created!")))
>> >
>> > ...but then we get:
>> >
>> > user=> (transparent-chan my-chan)
>> >
>> > CompilerException java.lang.RuntimeException: First argument to
>> def must
>> > be a Symbol, compiling... ; etc.
>> > user=>
>> >
>> > Hmm...still a problem. Let's see, when is the 'log-name' function
>> > getting run? Oh, at *run-time*...but we want it run at compile-time.
>> > So, knowing that, we can adjust it again:
>> >
>> > (defmacro transparent-chan [ch]
>> > `(do (def ~ch (async/chan))
>> > (def ~(log-name ch) (atom []))
>> > (println "new transparent channel created!")))
>> >
>> > Now we see:
>> >
>> > user=> (transparent-chan my-chan)
>> > new transparent channel created!
>> > nil
>> > user=> my-chan
>> > #<ManyToManyChannel
>> > clojure.core.async.impl.channels.ManyToManyChannel@7b3287a>
>> > user=> my-chan-log
>> > #<Atom@49d869e7: []>
>> > user=> my-chan-log
>> >
>> > Etc. I think that you need to keep playing with it and you'll get
>> it; it
>> > doesn't seem too far off.
>> >
>> > That said, if I were you I'd still try it the simpler way I proposed
>> > before--this seems like a lot of work for not a lot of payoff,
>> when you
>> > can just dump out logging information at the time you send or
>> receive a
>> > message. And in general creating vars like this dynamically is not
>> easy
>> > to reason about and can be dangerous. I would suggest putting
>> > dynamically created channels in a collection inside an atom if you
>> need
>> > to create them like this.
>> >
>> >> Later I was thinking about incorporating it into a gui to see
>> >> if it's possible to design an asynchronous message passing system
>> >> using drag and drop icons that represent pubs and subs, channels
>> with
>> >> a drop-down contents tab, and running listening processes.
>> >> I know this is probably out of my league, but I was just asking
>> >> myself how something like that might be implemented.
>> >
>> > I think it's totally possible and there's no reason it would be
>> out of
>> > your league. Just keep trying and asking questions here (and on
>> IRC too
>> > if you want to jump on, plenty of folks there willing to help out).
>> >
>> > DD
>> >
>> > (2014/05/12 17:26), gamma235 wrote:
>> >> Thank you for your answer David.
>> >>
>> >> I think I am confused about how to distinguish between a symbol
>> and a
>> >> variable, as I thought that the symbol being derefed pointed to
>> the atom
>> >> that it was made to define when transparent-chan was called.
>> >>
>> >> Also, I am trying to specifically solve the logging problem to
>> >> understand how I might use stored values or state outside the
>> scope of
>> >> the channel as a means of creating the illusion of referencing its
>> >> contents. Later I was thinking about incorporating it into a gui
>> to see
>> >> if it's possible to design an asynchronous message passing system
>> using
>> >> drag and drop icons that represent pubs and subs, channels with a
>> >> drop-down contents tab, and running listening processes. I know
>> this is
>> >> probably out of my league, but I was just asking myself how
>> something
>> >> like that might be implemented. I will of course continue to
>> learn and
>> >> reinforce the basics though on my own.
>> >>
>> >> Jesse
>> >>
>> >> On Monday, May 12, 2014 1:26:57 PM UTC+9, David Della Costa wrote:
>> >>
>> >> I apologize, apparently you can't use go-loop how I did below,
>> >>
>> >> => (def my-go-loop (async/go-loop [msg (async/<! c)] (println
>> "got
>> >> msg "
>> >> msg " from channel " 'c)))
>> >>
>> >> ...try this instead:
>> >>
>> >> (def my-go-loop (async/go-loop [] (let [msg (async/<! c)]
>> (println "got
>> >> msg " msg " from channel " 'c))))
>> >>
>> >> Sorry about that!
>> >>
>> >> DD
>> >>
>> >> (2014/05/12 13:21), Dave Della Costa wrote:
>> >> >
>> >> >> 1) I feel like it is a redundant to define bindings multiple
>> >> times in
>> >> >> my go's let exprs when the params have already been passed
>> in as
>> >> >> arguments. Is there a more idiomatic way to do this?
>> >> >
>> >> > I think the fact that you are re-binding in a let should
>> show you
>> >> that
>> >> > these variables are already in scope: that let is wholly
>> >> redundant, just
>> >> > remove it.
>> >> >
>> >> >
>> >> >> 2) Whenever I try to create a generic process to
>> automatically
>> >> >> generate a log-name for each channel and then call update,
>> I get a
>> >> >> 'symbol cannot be cast to atom' error. How can I get
>> around this? It
>> >> >> seems to happen even if I don't use the log-name function.
>> >> >
>> >> > It's simple: a symbol is not an atom. It's telling you
>> exactly
>> >> what you
>> >> > need to know: you cannot call swap! on a symbol. Make sure
>> your
>> >> atom is
>> >> > the first argument to swap! wherever you use it.
>> >> >
>> >> >
>> >> >> 3) Is there a better way to keep track of what's on a
>> channel that
>> >> >> doesn't use macros?
>> >> >
>> >> > You cannot look inside of a channel, but to do what you
>> want and
>> >> get a
>> >> > sense of how core.async works, I think you are on the right
>> track by
>> >> > logging as you put stuff in and take it out.
>> >> >
>> >> > That said, I would start by getting rid of the log and the
>> >> macro--these
>> >> > are unnecessary complications--and do things very simply:
>> >> >
>> >> > => (require '[clojure.core.async :as async])
>> >> > nil
>> >> > => (def c (async/chan))
>> >> > #'user/c
>> >> > => (def my-go-loop (async/go-loop [msg (async/<! c)]
>> (println "got
>> >> msg "
>> >> > msg " from channel " 'c)))
>> >> > #'user/my-go-loop
>> >> > => (defn put-and-print! [c msg] (println "putting msg " msg
>> " onto
>> >> > channel " 'c) (async/put! c msg))
>> >> > #'user/put-and-print!
>> >> > => (put-and-print! c "I am a message!")
>> >> > putting msg I am a message! onto channel c
>> >> > got msg I am a message! from channel c
>> >> > nil
>> >> > =>
>> >> >
>> >> > Printing out "channel c" is kind of silly since there is
>> only one,
>> >> but
>> >> > it sounds like you may want to do this with multiple
>> channels so
>> >> this is
>> >> > one way to print out the variable name--simply quote it.
>> >> >
>> >> > DD
>> >> >
>> >> > (2014/05/12 11:41), gamma235 wrote:
>> >> >> Hi everyone,
>> >> >>
>> >> >> I am getting my feet wet with core.async and am trying to
>> attach
>> >> atoms
>> >> >> to channels that update automatically and print out to the
>> >> console as
>> >> >> you take and put. This is not for anything serious, just a
>> way to
>> >> get
>> >> >> familiar with the behavior and functionality of the
>> library and
>> >> practice
>> >> >> my Clojure skills. Thanks in advaan
>> >> >>
>> >> >> Here is my code:
>> >> >>
>> >> >> (defn log-name [ch] (symbol (str ch '-log)))
>> >> >>
>> >> >> ;; Is this efficiently written?
>> >> >> (defmacro transparent-chan [ch]
>> >> >> (do
>> >> >> `(def ~ch (chan))
>> >> >> `(def (log-name ~ch) (atom []))
>> >> >> `(println "new transparent channel created!")))
>> >> >>
>> >> >> (defn- update [log v]
>> >> >> (do
>> >> >> (swap! log conj v)
>> >> >> (println "log test passed: " v " has been logged")
>> >> >> (println "channel contents: " @log)))
>> >> >>
>> >> >> (defn transparent-put [ch v]
>> >> >> (let [log (log-name ch)]
>> >> >> (go
>> >> >> (let [ch ch
>> >> >> v v]
>> >> >> (>! ch v)
>> >> >> (println v " has been successfully moved
>> through the
>> >> channel")))
>> >> >> (update log v)
>> >> >> (println "put test passed: " v " has been put on the
>> >> channel")
>> >> >> (println " rechecking channel contents: " @log)))
>> >> >>
>> >> >> (defn transparent-take [ch]
>> >> >> (go
>> >> >> (let [v (<! ch)
>> >> >> log-name (symbol (str ch '-log))]
>> >> >> (swap! log-name #(remove #{v} %))
>> >> >> (println v "has been removed from channel")))
>> >> >> (println " removal pending"))
>> >> >>
>> >> >>
>> >> >>
>> >> >> ;; tests
>> >> >> (transparent-chan c)
>> >> >> c
>> >> >> c-log
>> >> >> @c-log
>> >> >> (transparent-put c 42)
>> >> >> (transparent-take c)
>> >> >>
>> >> >>
>> >> >>
>> >> >> My main questions are regarding variable scope:
>> >> >> 1) I feel like it is a redundant to define bindings multiple
>> >> times in my
>> >> >> go's let exprs when the params have already been passed in as
>> >> arguments.
>> >> >> Is there a more idiomatic way to do this?
>> >> >>
>> >> >> 2) Whenever I try to create a generic process to
>> automatically
>> >> generate
>> >> >> a log-name for each channel and then call update, I get a
>> 'symbol
>> >> cannot
>> >> >> be cast to atom' error. How can I get around this? It
>> seems to
>> >> happen
>> >> >> even if I don't use the log-name function.
>> >> >>
>> >> >> 3) Is there a better way to keep track of what's on a
>> channel that
>> >> >> doesn't use macros?
>> >> >>
>> >> >> --
>> >> >> You received this message because you are subscribed to
>> the Google
>> >> >> Groups "Clojure" group.
>> >> >> To post to this group, send email to [email protected]
>> >> <javascript:>
>> >> >> 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] <javascript:>
>> >> >> For more options, visit this group at
>> >> >> http://groups.google.com/group/clojure?hl=en
>> <http://groups.google.com/group/clojure?hl=en>
>> >> <http://groups.google.com/group/clojure?hl=en
>> <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] <javascript:>
>> >> >> <mailto:[email protected] <javascript:>>.
>> >> >> For more options, visit https://groups.google.com/d/optout
>> <https://groups.google.com/d/optout>
>> >> <https://groups.google.com/d/optout
>> <https://groups.google.com/d/optout>>.
>> >>
>> >> --
>> >> You received this message because you are subscribed to the Google
>> >> Groups "Clojure" group.
>> >> To post to this group, send email to [email protected]
>> <javascript:>
>> >> 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] <javascript:>
>> >> For more options, visit this group at
>> >> http://groups.google.com/group/clojure?hl=en
>> <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] <javascript:>
>> >> <mailto:[email protected] <javascript:>>.
>> >> For more options, visit https://groups.google.com/d/optout
>> <https://groups.google.com/d/optout>.
>>
>> --
>> 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]
>> <mailto:[email protected]>.
>> For more options, visit https://groups.google.com/d/optout.
--
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.