Hi Mark, In Clojuratica I make what I think is "good, clean, compelling use" of dynamic vars. I rewrote the code to use dynamic vars after I found that doing it the other way became unwieldy and inelegant.
To simplify a little, the API consists of just one main function, let's call it math-evaluate. Every time the user calls math-evaluate, he or she can specify any of a number of flags. Just for illustration, let's say two of these flags are :flag1 and :flag2. The math-evaluate function parses the flags and places them in a map called *options* (or options before I was using dynamic vars). It then calls into the core functions of the code base and returns the result. The core functions call one another in complex ways. There are scores of core functions. All of them have need to have access to the options map, if not for their own consumption then for passing to other core functions. Without dynamic vars, every single function in my code base would need to have an options argument. Moreover, every mutual call between these scores of functions would need to include the options map as an argument. I did it this way for a while, and it was painful. Moreover, if in the future I decided that every core function needed access to *two* of these global-within-the-dynamic-scope vars instead of one, I would need to edit the signature of every function and edit every mutual call between the functions. It turned out that this actually happened: I decided I needed another map to store a few I/O bindings (it's called *kernel*). Because I was using dynamic vars, I was able to change just one location in my code---the namespace where the dynamics are interned---instead of several hundred locations. The trade-off is the following. When I need to return a function or lazy seq I need to close over the *options* and *kernel* vars by jumping through the hoops Meikel has documented. There are only five or six such places in the code, so I'm more than happy to do this. It feels quite elegant to me, although I'd like a little more syntactic sugar. Note that the dynamic vars are solely for my convenience as a programmer, not part of the API of the software. I shield them from the user, so if the user tried to bind *options* him- or herself it would have no effect on the code. Every call to math-evaluate binds the dynamic vars anew on the basis of the flags passed. My use of dynamics is an implementation detail. The source is on github. The "real-laziness" branch is the newest and uses bound lazy-seqs the most, particularly in clojuratica.base.parse. Comments on this usage welcome. Garth On Tue, Nov 24, 2009 at 1:43 AM, Mark Engelberg <mark.engelb...@gmail.com>wrote: > Meikel's blog post quotes: > "running into a lot of such trouble is a sign, that you misuse dynamic > variables. Use them wisely." > > I'd like to see examples of what you think is a good, clean, > compelling use of dynamic variables that are properly used wisely. > > My own experience is that if the code is simple enough for you to > analyze the use of binding and be sure it is correct, then the code is > also simple enough to have easily written in another way (perhaps > using explicit parameter passing). On the other hand, if the use of > binding is complex enough to really matter, it is also sufficiently > complex you can't be 100% sure binding will do what you expect. > > I even somewhat question the places where Clojure internally uses > bindings. For example, if you use with-precision to try to control > floating point behavior within a structure that potentially has some > deep laziness (like a tree) that can't easily be forced with a doall, > you're in for a surprise. > > I would like to be proven wrong, so I'm serious about wanting to see > good examples of dynamic binding. > > -- > 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<clojure%2bunsubscr...@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 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