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