With this approach how would I test the individual functions defined
inside of the let? Wouldn't they be invisible to me and the test
framework which would only see "sell-or-rent"?

On Feb 18, 4:27 pm, John Williams <j...@pobox.com> wrote:
> 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

Reply via email to