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

Reply via email to