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

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

Reply via email to