Re: Clojure equivalent of special common lisp vars: still looking for that zen place...
Sometimes you do want a mutable thing with thread-local binding, noir does this for it's mutable session-flash stuff: https://github.com/noir-clojure/lib-noir/blob/master/src/noir/session.clj#L95 I don't really recommend the approach, but I could see it being convenient. On Mon, May 5, 2014 at 1:38 PM, John Gabriele wrote: > On Saturday, May 3, 2014 10:53:40 AM UTC-4, Bob Hutchison wrote: >> >> >> On May 3, 2014, at 9:45 AM, Dave Tenny wrote: >> >> I'm still struggling with how to write the most readable, simple clojure >> code >> to deal with dynamically bindings. >> >> What is the graceful clojure equivalent of common lisp special variables >> for the following scenario. >> >> If I were writing common lisp I'd just do something like (pardon if my >> lisp is rusty here): >> >> (defvar *x* 1) >> ... do stuff with *x* ... >> (setq *x* 2) >> ... do stuff with *x* ... >> (let ((*x* 3)) (do stuff with *x*...) >> ;; do stuff with *x* that's currently at 2 >> >> >> The way I'm tempted to do this in clojure is >> >> (def ^{:dynamic true} *x* (atom 1)) >> ... do stuff with @*x* ... >> (reset! *x* 2) >> ... do stuff with @*x* ... >> (binding [*x* (atom 3)] (do stuff with @*x*)) >> >> >> You can also just write it: >> >> (def ^:dynamic *x* (atom 1)) >> >> which is a little less verbose. >> >> > My understanding is that it's more common to *either* > > * use `(def ^:dynamic *x* 1)`, *or* > * use `(def x (atom 1))`, > > but not both at the same time. > > That is to say, either you specifically want at dynamic var which you can > change via a `binding`, or else you just want a global mutable (the atom). > > Would love to be corrected if I'm wrong though. > > -- John > > -- > 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. > -- 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.
Re: Clojure equivalent of special common lisp vars: still looking for that zen place...
On Saturday, May 3, 2014 10:53:40 AM UTC-4, Bob Hutchison wrote: > > > On May 3, 2014, at 9:45 AM, Dave Tenny > > wrote: > > I'm still struggling with how to write the most readable, simple clojure > code > to deal with dynamically bindings. > > What is the graceful clojure equivalent of common lisp special variables > for the following scenario. > > If I were writing common lisp I'd just do something like (pardon if my > lisp is rusty here): > > (defvar *x* 1) > ... do stuff with *x* ... > (setq *x* 2) > ... do stuff with *x* ... > (let ((*x* 3)) (do stuff with *x*...) > ;; do stuff with *x* that's currently at 2 > > > The way I'm tempted to do this in clojure is > > (def ^{:dynamic true} *x* (atom 1)) > ... do stuff with @*x* ... > (reset! *x* 2) > ... do stuff with @*x* ... > (binding [*x* (atom 3)] (do stuff with @*x*)) > > > You can also just write it: > > (def ^:dynamic *x* (atom 1)) > > which is a little less verbose. > > My understanding is that it's more common to *either* * use `(def ^:dynamic *x* 1)`, *or* * use `(def x (atom 1))`, but not both at the same time. That is to say, either you specifically want at dynamic var which you can change via a `binding`, or else you just want a global mutable (the atom). Would love to be corrected if I'm wrong though. -- John -- 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.
Re: Clojure equivalent of special common lisp vars: still looking for that zen place...
re: binding behavior, I've only been using clojure since 1.5.1, but in my travels I get the impression that the binding form didn't always enforce the variable to be declared dynamic, and so maybe didn't behave the way you'd expect if the ^:dynamic was missing from the target of the binding form. Just guessing. On Sat, May 3, 2014 at 11:08 AM, Lee Spector wrote: > > On May 3, 2014, at 9:45 AM, Dave Tenny wrote: > > > > The way I'm tempted to do this in clojure is > > > > (def ^{:dynamic true} *x* (atom 1)) > > ... do stuff with @*x* ... > > (reset! *x* 2) > > ... do stuff with @*x* ... > > (binding [*x* (atom 3)] (do stuff with @*x*)) > > > Having also come from Common Lisp and having once done things similar to > your suggestion in Clojure, I got burned by the fact (I *think* it was a > fact) that "binding" created thread-local bindings that reverted to global > bindings inside of code executed in another thread, e.g. in a pmap buried > somewhere within the code executed within the binding form. I found this to > be unexpected and problematic. > > Trying some simple examples with your outline, however, I don't see this > happening. And I wonder if it's because of changes in more recent versions > of Clojure related to ^{:dynamic true}. > > Does anyone know if the reversion of "binding"-bound vars to global > bindings when crossing thread boundaries has really been eliminated? Or am > I just not seeing it because my examples have been too simple? > > -Lee > > -- > 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 a topic in the > Google Groups "Clojure" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/clojure/Wh1M345Y5u4/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > 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.
Re: Clojure equivalent of special common lisp vars: still looking for that zen place...
On Sat, May 3, 2014 at 10:53 AM, Bob Hutchison wrote: > You can also just use ‘def’ to redefine the global binding. Thanks, though in this case it's a mixed use. In some cases I want to change the root of the global binding, in others I want to rebind to a new value in some context without changing the value seen in other contexts. -- 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.
Re: Clojure equivalent of special common lisp vars: still looking for that zen place...
On May 3, 2014, at 9:45 AM, Dave Tenny wrote: > > The way I'm tempted to do this in clojure is > > (def ^{:dynamic true} *x* (atom 1)) > ... do stuff with @*x* ... > (reset! *x* 2) > ... do stuff with @*x* ... > (binding [*x* (atom 3)] (do stuff with @*x*)) Having also come from Common Lisp and having once done things similar to your suggestion in Clojure, I got burned by the fact (I *think* it was a fact) that "binding" created thread-local bindings that reverted to global bindings inside of code executed in another thread, e.g. in a pmap buried somewhere within the code executed within the binding form. I found this to be unexpected and problematic. Trying some simple examples with your outline, however, I don't see this happening. And I wonder if it's because of changes in more recent versions of Clojure related to ^{:dynamic true}. Does anyone know if the reversion of "binding"-bound vars to global bindings when crossing thread boundaries has really been eliminated? Or am I just not seeing it because my examples have been too simple? -Lee -- 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.
Re: Clojure equivalent of special common lisp vars: still looking for that zen place...
On May 3, 2014, at 9:45 AM, Dave Tenny wrote: > I'm still struggling with how to write the most readable, simple clojure code > to deal with dynamically bindings. > > What is the graceful clojure equivalent of common lisp special variables for > the following scenario. > > If I were writing common lisp I'd just do something like (pardon if my lisp > is rusty here): > > (defvar *x* 1) > ... do stuff with *x* ... > (setq *x* 2) > ... do stuff with *x* ... > (let ((*x* 3)) (do stuff with *x*...) > ;; do stuff with *x* that's currently at 2 > > > The way I'm tempted to do this in clojure is > > (def ^{:dynamic true} *x* (atom 1)) > ... do stuff with @*x* ... > (reset! *x* 2) > ... do stuff with @*x* ... > (binding [*x* (atom 3)] (do stuff with @*x*)) Inside the binding you can call set! if you must. You can also just use 'def' to redefine the global binding. It says this: "Using def to modify the root value of a var at other than the top level is usually an indication that you are using the var as a mutable global, and is considered bad style. Consider either using binding to provide a thread-local value for the var, or putting a ref or agent in the var and using transactions or actions for mutation." in the docs at http://clojure.org/special_forms#def which is roughly what you did with the atom. But it'll work. You can also just write it: (def ^:dynamic *x* (atom 1)) which is a little less verbose. Cheers, Bob > > > Is that the simplest way to map between the two language scenarios? > Or is there something simpler, perhaps using some var-* apis or what have you? > > > > -- > 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. -- 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.
Clojure equivalent of special common lisp vars: still looking for that zen place...
I'm still struggling with how to write the most readable, simple clojure code to deal with dynamically bindings. What is the graceful clojure equivalent of common lisp special variables for the following scenario. If I were writing common lisp I'd just do something like (pardon if my lisp is rusty here): (defvar *x* 1) ... do stuff with *x* ... (setq *x* 2) ... do stuff with *x* ... (let ((*x* 3)) (do stuff with *x*...) ;; do stuff with *x* that's currently at 2 The way I'm tempted to do this in clojure is (def ^{:dynamic true} *x* (atom 1)) ... do stuff with @*x* ... (reset! *x* 2) ... do stuff with @*x* ... (binding [*x* (atom 3)] (do stuff with @*x*)) Is that the simplest way to map between the two language scenarios? Or is there something simpler, perhaps using some var-* apis or what have you? -- 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.