John: The options do effectively change once outside the dynamic scope because there are default options. If the lazy-seq is evaluated outside the dynamic scope it will use these default options. Within the dynamic scope it will use the bound options.
I'm considering giving up laziness, but the sequences being returned are time-consuming to create and there's a potential benefit to the user to keeping them lazy. Meikel: One of the key pieces of code is a recursive parser. Highly simplified: I have a userland function (fn parse [expression & options] ... ) which calls a backend function (ns parse) (fn parse [expression] ... (cond (sequence? expression) (parse-expression-sequence expression) (other-expr-type? expression) (parse-so-and-so expression) (atomic-expression? expression) (parse-atom expression) ... ) which, depending on the nature of expression, calls an array of different parser functions, some of which recursively call back to parse/parse. Again, highly simplified: (fn parse-expression-sequence [expression] (map parse (seq expression)) This kind of recursive calling happens a lot, in a lot of different functions. (In this parser I also have a non-stack-blowing version of the parser for deep data structures, which you Meikel suggested a couple weeks/months ago, but in other parts of my code (a recursive s-expression reader, for instance) I'm not worried about data-structure depth so am using only mutually recursive functions exclusively. This may bite me one day, but for now it's easy and works well for even quite deep structures.) The goal is to try to avoid having to pass options in each of the jointly recursive calls. The "fixed" bindings version isn't any better (thanks for the suggestion though) because the function being mapped is often one of the functions I'm trying to avoid giving extra arguments. Is bound-fn less efficient because it has to make a full copy of all dynamically bound variables on each call? Thanks. On Wed, Oct 14, 2009 at 3:19 AM, Meikel Brandmeyer <m...@kotka.de> wrote: > > Hi, > > I think it depends on what your options are actually doing, what has > to be so configurable. Maybe you can extract this configurability with > a more functional approach? For example instead of specifying a > algorithm to use in the options map, make it a parameter of the > backend function and let the frontend plugin a suitable fn depending > on the user choice. Or store away such information in your data > structure and use multimethods to dispatch on this information. In how > far such alternatives are viable depends really on the nature of your > options. > > Another solution is to "fix" the bindings for the lazy-seqs: > > (defn uses-foo-and-bar-options > [stuff] > (let [{:keys [foo bar]} *options*] > (map #(do-stuff-with foo bar %) stuff))) > > bound-fn will also remedy this problem: > > (defn uses-the-options > [stuff] > (map (bound-fn [x] (do-stuff-with (:foo *options*) x)) stuff)) > > However this will most likely not be the fastest approach. > > In a totally representative query ;), I thought about my code. And I > almost never find the need for binding. If I use it, it is really in a > local context. Eg. rebinding *out* for a couple of local prints. > > Maybe you can post some example, what you want to do? Then it is > easier to come up with some concrete ideas. > > Sincerely > Meikel > > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---