> 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 clo...@googlegroups.com > >> <javascript:> > >> >> Note that posts from new members are moderated - please be > >> patient with > >> >> your first post. > >> >> To unsubscribe from this group, send email to > >> >> clojure+u...@googlegroups.com <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 clojure+u...@googlegroups.com <javascript:> > >> >> <mailto:clojure+u...@googlegroups.com <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 clo...@googlegroups.com > <javascript:> > >> Note that posts from new members are moderated - please be > patient with > >> your first post. > >> To unsubscribe from this group, send email to > >> clojure+u...@googlegroups.com <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 clojure+u...@googlegroups.com <javascript:> > >> <mailto:clojure+u...@googlegroups.com <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 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 > <mailto:clojure+unsubscr...@googlegroups.com>. > 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 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.