I'm no Clojure guru myself, but one approach you may want to consider is nest all your auxiliary functions inside the main function, and use ordinary let-bindings the same way you've been trying to use global bindings:
(defn sell-or-rent [{:keys [supplied-1 supplied-2]}] (let [derived-1 (+ 1 supplied-1) derived-2 (* 2 supplied-2)] (letfn [(f [x y z] ...) (g [x] ...)] ...))) This has the disadvantage of indenting all your helper functions much more than they would be otherwise, but it gets the job done without any messy global variables or thunks. If you want to expose more functions than just sell-or-rent, you could write some very OO-flavored code: ;; Define a function to create objects. (defn pseudo-constructor [{:keys [supplied-1 supplied-2]}] (let [member-var-1 (+ 1 supplied-1) member-var-2 (* 2 supplied-2)] (letfn [(private-method-1 [] "priv1") (private-method-2 [] "priv2")] {:public-method-1 (fn [x y z] "pub1") :public-method-2 (fn [x y] "pub2")}))) ;; Use the object. (let [obj (pseudo-constructor {:supplied-1 1 :supplied-2 2})] (println ((:public-method-1 obj) "x" "y" "z")) (println ((:public-method-2 obj) "x" "y"))) --jw On Mon, Feb 15, 2010 at 11:24 AM, Yaron <ygol...@gmail.com> wrote: > I am writing a calculator to figure out if I should sell or rent my > home using Clojure. This is my first Clojure program so I'm about as > wet behind the ears as it gets. So far everything is actually going > really well (reminds me of the fun I had with Scheme in college) but > for one thing. My calculator needs 30+ arguments from the user in > order to run. Furthermore I have a bunch of secondary values that are > derived from the arguments the user submits. > > So imagine the user submits a value A. I will have a value B whose > definition will be something like (+ 1 A) (yes, more complex in > reality, but you get the idea). > > If I were back in Java or C# I would define a class, submit A (and > it's 29+ friends) in the constructor and then create a property on the > class B. > > In Clojure I have taken a different approach. I first create (def *A* > 3) where 3 is a completely bogus value I just made up. Then at run > time I use bindings to re-bind A to the actual value the user passed > in. > > But my problem is, what to do about B? I thought of doing something > like (def *B* 3) and then in the binding passing in a function like > (defn B-Gen [] (+ *A* 1)) to create a new binding to B but I quickly > realized this would be a bug inducing nightmare. If I forget to > include one of the derived values in the binding or put them in the > wrong order then I would get the wrong value. > > So what I currently do is: > (def *A* 3) ; A bogus value that will later be rebound > (defn B [] (+ *A* 3)) > > The good news is, that this works and doesn't require any book > keeping. > > The bad news is that it's ugly. If I want to do something trivial like > divide B by 2 I have to call B as a function(/ (B) 2) instead of the > more natural (/ B 2). And of course this approach is pretty > unfortunate from a performance perspective as I'm constantly having to > recalculate what are effectively static values. Yes, I could use > memoization but many of these values are pretty trivial (usually just > algebra equations) and I suspect the overhead of memoization exceeds > the perf improvement. > > But in any case the whole approach of having to take what really are > static values and turn them into functions feels really hacky. So my > guess is that I'm thinking about this problem the wrong way. I'm stuck > in my old imperative/OO constructor world. > > What's the right way to think about primary values that will be > rebound (once) that then have dependent values that need to be > recalculated when that rebinding happens? > > Thanks, > > Yaron > > -- > 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