Re: newbie question: Please help me stop creating constructors

2010-03-01 Thread Jarkko Oranen


On Mar 1, 9:55 am, Richard Newman holyg...@gmail.com wrote:

    (defn house-sale-profit
      [house-sales-price house-sale-expenses]
      (- house-sales-price house-sale-expenses))

I'd like to note that if you do this, you might just as well use the -
function directly. It's not as flexible if the profit calculation
changes, but until there's a real need, it just feels like
overabstraction.
  (let [profit (- house-sales-price house-sale-expenses)]
 ...)
is perfectly reasonable. The same applies to calculating months-in-
business.

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


Re: newbie question: Please help me stop creating constructors

2010-03-01 Thread Andrzej
On Thu, Feb 18, 2010 at 3:36 PM, Richard Newman holyg...@gmail.com wrote:
 You express the equations as functions. Turning your equation notation into
 function notation -- I'll use Haskell's as an example:

        OpportunityCost = Rent - Sell

 becomes

        opportunityCost r s = r - s

 or in Clojure:

        (defn opportunity-cost [r s]
          (- r s))

What to do if we don't know which of the equation variables are
unknowns? Let's say that the user may choose whether to input Rent
and Sell, or Rent and opportunityCost. I can imagine writing
some code like this:

(defn opportunity-cost [opportunity-cost-in rent-in sell-in]
   (if (nil? opportunity-cost-in)
   (- rent-in sell-in)
   opportunity-cost-in))

(defn rent [opportunity-cost-in rent-in sell-in]
   (if (nil? rent-in)
   ...)

(defn sell [opportunity-cost-in rent-in sell-in]
   (if (nil? sell-in)
   ...)

but complexity of such expressions quickly grows as dependencies
between variables become more complex. Is there any
technique/framework for handling such calculations automatically? I
have a vague impression that this is what logic programming languages
are about. How would one implement such calculations in Clojure?

Going further, what to do if the equation is underspecified (for
example, if the user has only input Rent) and we want to do
something more useful than just fail. This would require us to do the
calculations symbolically. Can Clojure help here somehow? What would
be a minimal CAS framework in Clojure?

-Andrzej

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


Re: newbie question: Please help me stop creating constructors

2010-03-01 Thread Richard Newman

I'd like to note that if you do this, you might just as well use the -
function directly.


Of course; this was merely for the sake of illustration.

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


Re: newbie question: Please help me stop creating constructors

2010-03-01 Thread Richard Newman

but complexity of such expressions quickly grows as dependencies
between variables become more complex. Is there any
technique/framework for handling such calculations automatically? I
have a vague impression that this is what logic programming languages
are about. How would one implement such calculations in Clojure?


As Johnny mentioned: this is a solver. Doing it in Clojure means  
writing something rather more complicated than a simple calculator!  
Clojure is not a logic programming language.


You might find a cell/dataflow framework useful, which essentially  
gives you spreadsheet-like dataflow:


  http://richhickey.github.com/clojure-contrib/dataflow-api.html

best introduced in its original Common Lisp form:

  http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html

but you'll still have to do some manual decision-making. (Just like in  
a spreadsheet, you have to write the formulae...)


You might also (depending on how things fall out) find some kind of  
table-based or multimethod-based approach to be adequate (e.g., making  
two different kinds of `sell` evaluation based on whether some value  
is nil). That will reduce the number of explicit branches in your code.


If neither of those helps, then your best bet is to spend a little  
time with, say, Mathematica, Excel, and Prolog (or one of its  
successors). Those might well be better systems for handling this kind  
of web of dependencies.


If you want a Lisp syntax for Prolog, try Allegro Common Lisp.

http://www.franz.com/products/prolog/index.lhtml

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


Re: newbie question: Please help me stop creating constructors

2010-03-01 Thread Yaron
I don't think that dataflow works quite right in my case because, if I
understood Mr. Straszheim's posts correctly then dataflows can't have
cycles and I have cycles all over the place. Unfortunately this isn't
visible in the example I gave because I used Sell which doesn't have
cycles. Rent on the other hand is recursive and cyclic.

On Mar 1, 7:31 am, Richard Newman holyg...@gmail.com wrote:
  but complexity of such expressions quickly grows as dependencies
  between variables become more complex. Is there any
  technique/framework for handling such calculations automatically? I
  have a vague impression that this is what logic programming languages
  are about. How would one implement such calculations in Clojure?

 As Johnny mentioned: this is a solver. Doing it in Clojure means  
 writing something rather more complicated than a simple calculator!  
 Clojure is not a logic programming language.

 You might find a cell/dataflow framework useful, which essentially  
 gives you spreadsheet-like dataflow:

    http://richhickey.github.com/clojure-contrib/dataflow-api.html

 best introduced in its original Common Lisp form:

    http://smuglispweeny.blogspot.com/2008/02/cells-manifesto.html

 but you'll still have to do some manual decision-making. (Just like in  
 a spreadsheet, you have to write the formulae...)

 You might also (depending on how things fall out) find some kind of  
 table-based or multimethod-based approach to be adequate (e.g., making  
 two different kinds of `sell` evaluation based on whether some value  
 is nil). That will reduce the number of explicit branches in your code.

 If neither of those helps, then your best bet is to spend a little  
 time with, say, Mathematica, Excel, and Prolog (or one of its  
 successors). Those might well be better systems for handling this kind  
 of web of dependencies.

 If you want a Lisp syntax for Prolog, try Allegro Common Lisp.

 http://www.franz.com/products/prolog/index.lhtml

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


Re: newbie question: Please help me stop creating constructors

2010-02-28 Thread Yaron
Richard, I spent quite a bit of time thinking about what you said.

So I rewrote the whole kit and kaboodle. My understanding of your mail
led me to take the approach of defining functions who take as
arguments the invariant values and who output functions that take
variant values. For example:

(defn house-sale-profit
 [house-sales-price house-sale-expenses]
 (fn [m]
  (- (house-sales-price m) (house-sale-expenses m

In this example both house-sales-price and house-sale-expenses are
actually themselves functions which I would have had to have called
previously to get their instance functions and passed in as arguments.

To test out this idea I decided to implement all the functions needed
to implement the sell function from my paper. But when I was done and
wanted to actually calculate a sell value I had to write something
like:

(defn sell-calculator
 [{:keys [real-monthly-opportunity-cost months-to-find-tenant months-
in-lease lease-cycles months-to-sell excise-tax
months-in-loan original-loan-amount monthly-loan-interest other-
sales-fees-0 monthly-inflation-rate
selling-agent-fee-type selling-agent-fee-number buying-agent-fee-
type buying-agent-fee-number
house-sales-price-0 loan-month-at-start]}]
 (let [inflate (inflate monthly-inflation-rate)
   house-sales-price (house-sales-price house-sales-price-0
inflate)
   buying-agent-fee (agent-fee inflate buying-agent-fee-type
buying-agent-fee-number house-sales-price)
   selling-agent-fee (agent-fee inflate selling-agent-fee-type
selling-agent-fee-number house-sales-price)
   other-sales-fees (other-sales-fees other-sales-fees-0
inflate)
   remaining-loan-balance (remaining-loan-balance months-in-loan
original-loan-amount monthly-loan-interest loan-month-at-start)
   house-sale-expenses (house-sale-expenses house-sales-price
excise-tax buying-agent-fee selling-agent-fee other-sales-fees
remaining-loan-balance)
   house-sale-profit (house-sale-profit house-sales-price house-
sale-expenses)
   months-in-business (months-in-business months-to-find-tenant
months-in-lease lease-cycles months-to-sell)]
(sell house-sale-profit real-monthly-opportunity-cost months-in-
business)))

Writing the previous wasn't much fun and I recognized that I would
have to build the equivalent for testing all the various sub-functions
and I can only imagine what trying to do any kind of refactoring or
adding new functions would be like.

But then it occurred to me that all I was really doing was building up
a parse tree and that is something that computers are really good at.
So why not just have the computer do the work for me? So I wrote a
function called fill-map. It takes a keyword that maps to the name of
a function and a map that contains all the user arguments. It turn
returns a map that contains the submitted function and all of its
dependent functions. (Having the whole map including the dependent
functions is extremely useful for testing)

(defn fill-map
 ([func-name-keyword filled-map] (fill-map func-name-keyword filled-
map []))
 ([func-name-keyword filled-map ancestorvector]
  {:pre [(keyword? func-name-keyword) (map? filled-map) (vector?
ancestorvector)]}
  (if (contains? filled-map func-name-keyword)
   filled-map
   (do
(throw-if-in-seq func-name-keyword ancestorvector)
(let [func-name-symbol (keyword-to-symbol func-name-keyword)
  func (func-keyword-to-func-pointer func-name-keyword)
  func-arguments (func-keyword-to-func-keyword-arglist func-
name-keyword)
  ancestorvector (conj ancestorvector func-name-keyword)
  filled-map (reduce #(fill-map %2 %1 ancestorvector) filled-
map func-arguments)]
 (assoc filled-map func-name-keyword (apply func (map #(filled-
map %1) func-arguments

I also wrote:
(defn stack-em
 [func-name-keyword filled-map]
 ((fill-map func-name-keyword filled-map) func-name-keyword))

So now I can just say:

(defn sell-calculator
 [userargs]
 (stack-em :sell userargs))

The previous creates the same parse map as I manually created above
but in a fully automated fashion. And if I change any of the
signatures, dependencies, stick in new things, etc. it's no problem,
everything gets automatically regenerated.

You can see the whole program at 
http://www.goland.org/simple-reverse-rent-or-sell.clj

So is this the way you would approach this problem in Clojure?

  Thanks,

   Yaron

On Feb 19, 10:15 pm, Richard Newman holyg...@gmail.com wrote:
  I have to think that's preferable to submitting 30+ arguments to rent
  and sell.

  Or were you suggesting a different approach?

 The different approach only works with a different approach :)

 The way you've structured run-calculator, using the map is best,  
 because 30 arguments is crazy.

 Your need to pass 30 arguments to rent and sell because they need to  
 obtain or compute all of their intermediate values. You have a tree,  
 with rent and sell doing all the work.

 The alternative 

Re: newbie question: Please help me stop creating constructors

2010-02-28 Thread Richard Newman

So I rewrote the whole kit and kaboodle. My understanding of your mail
led me to take the approach of defining functions who take as
arguments the invariant values and who output functions that take
variant values. For example:


I'm not sure how much functional programming experience you have, but  
you've essentially discovered a kind of currying.


http://en.wikipedia.org/wiki/Currying

That is, you're taking a function house-sale-profit, in terms of house- 
sales-price (a function), house-sale-expenses (a function), and m, and  
fixing the first two values, returning a function in terms of m.


This is seamless in Haskell; less so in Clojure. See the built-in  
function `partial`.


When you wrote

  (defn house-sale-profit
[house-sales-price house-sale-expenses]
(fn [m]
  (- (house-sales-price m) (house-sale-expenses m

and used it like this:

  (let [...
house-sale-profit-fn (house-sale-profit house-sales-price  
house-sale-expenses)

...]
...)

you could just as easily have written:


  (defn house-sale-profit
[house-sales-price house-sale-expenses m]
(- (house-sales-price m) (house-sale-expenses m)))

and used it like this:

  (let [...
house-sale-profit-fn (partial house-sale-profit house-sales- 
price house-sale-expenses)

...]
...)

This makes house-sale-profit a perfectly normal function, but still  
allows you to partially evaluate it to yield a closure.




In this example both house-sales-price and house-sale-expenses are
actually themselves functions which I would have had to have called
previously to get their instance functions and passed in as arguments.


By doing this you're pretty much writing your own interpreter, as you  
figured out :)




So is this the way you would approach this problem in Clojure?


No. (However, consider that I'm as likely to be wrong as anybody else,  
and also that you're learning a ton by trying different approaches!)


I would do things much more simply: rather than (to take your example)  
defining house-sale-profit in terms of two functions and a month  
value, which is threaded into those functions (providing opportunity  
for breakage should the signature of, say, house-sales-price change),  
I would simply *define house-sale-profit in terms of the sales price  
and expenses*. Rely on the price and the expenses having been  
calculated outside the function.


No nonsense with throw-if-in-seq and all the other complicated  
machinery you have built.



  (defn house-sale-profit
[house-sales-price house-sale-expenses]
(- house-sales-price house-sale-expenses))


This is the literal definition of profit; you can write tests for this  
with just two numbers. If your expenses don't care about a number of  
months, or they care about something else, then just pass in a  
different value -- no futzing with functions. It's more efficient, too  
-- no anonymous functions.


For a single invocation you're only using one value of m, with one  
house sales price, and one set of expenses. Just put them in the let!



(let [m from the user
  price ...
  expenses ...
  profit (house-sale-profit price expenses)
  ...]
  ...)


I've done this for some of your functions:

http://twinql.com/tmp/rent.clj

I haven't tried actually using it to compute anything, but it should  
give you an idea of the style I'd use.


I would guess that the whole program, neatly laid out and commented,  
should come to only a couple hundred lines. Each individual function  
is trivially testable and reusable, as is every composition of  
functions that goes into computing the final answer.


If you want to be neater, split `sell-calculator` into two or more  
functions; perhaps one which walks through the rent calculation, and  
another which walks through the house sale calculation. That way each  
individual function remains short and sweet.


Note that I still curry some functions (e.g., inflate), and if I  
bothered to implement the agent fees (which are inflation-linked) I  
might do it by passing in that curried `inflate` function. (Then  
again, I might not, if I can phrase them in terms of constant values  
which are computed elsewhere.) Most of the intermediate values are  
simply computed directly.


Note also that, if you wished, you could completely eliminate the  
`let` form, turning this whole calculation into a single (slightly  
redundant) tree. I don't advocate that as particularly good style, but  
it's possible.


Ultimately, all you're doing here is writing a set of functions and  
combining them together to produce an answer: a simple matter of  
traditional programming. It's not rocket surgery (as they say  
nowadays), and so any solution which requires you to write code to  
detect recursive calls, look up function names at runtime, manage a  
huge intermediate map of results, etc. is probably a sign that you're  
over-engineering things.


I would have used almost the 

Re: newbie question: Please help me stop creating constructors

2010-02-19 Thread Yaron
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.comclojure%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

Re: newbie question: Please help me stop creating constructors

2010-02-19 Thread John Williams
Right, nesting everything inside a single function makes it impossible to
unit test the inner functions--they don't even have names in the global
scope!  In retrospect, I think the solution I posted is more cute than it is
practical.  Passing around a map of intermediate values seems to be the
winner all around, but it still seems a little odd to me.  Idiomatic Clojure
code manipulates maps far more than I've seen in any other language.

On Fri, Feb 19, 2010 at 11:30 AM, Yaron ygol...@gmail.com wrote:

 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 

Re: newbie question: Please help me stop creating constructors

2010-02-19 Thread Yaron

 Looks pretty good to me. I like your use of preconditions and the  
 number of tests. I think your indentation is a little deep (I go for  
 two spaces, myself), and I never use :Capital keywords, but otherwise  
 great.

The indentation was just what the Clojure plugin for Eclipse was set
to by default.

As for capitalization I've never been completely clear on what the
normal naming rules in Clojure are.

 You might be interested in the `are` macro to make your test code  
 simpler:


Thanks for pointing this out. Very useful. I've already started
adapting some of my tests.

 One suggestion:

 Rather than having two phases of derived args, and calling functions  
 with arguments like:

   (total-house-depreciation args-and-mib)

 I'd save that step and adjust total-house-depreciation, year-sold,  
 etc. to take an additional months-in-business argument:

 (defn total-house-depreciation
     The total amount of depreciation on the rental property taken  
 over the period we were in business
     [args months-in-business]
     ...)

 Then you can change your derived-args function to:

 (defn derived-args
         [{:keys [months-to-find-tenant months-in-lease lease-cycles months-to-
 sell] :as args}]
    (assoc args
      :months-in-business (months-in-business months-to-find-tenant  
 months-in-lease lease-cycles months-to-sell)
      :total-house-depreciation (total-house-depreciation args months-
 in-business)
      :year-sold (year-sold args months-in-business)
      :months-actively-renting (months-actively-renting months-to-find-
 tenant months-in-lease lease-cycles)))

 No lets at all.

The reason why I didn't make months-in-business an explicit arg for
total-house-depreciation and year-sold is because both functions are
thin wrappers for underlying functions that take args. So if I broke
out months-in-business at the top I'd just have to invent the
equivalent of the args-and-mib variable farther down to give the
functions they are wrapping what they are expecting.

BTW, the only place I had to use let in anything even like this manner
was derived-args. Everywhere else I can just pass args with no voodoo,
no lets, nothing. All the 'voodoo' is just in derived-args and
creating derived-args.

 You'll see then that it's a small step from there to my suggested  
 functional end game, which eliminates the passing of the args map  
 altogether: derived-args would extract all the named arguments and  
 pass just the specific ones to each function. No big deal, though;  
 there are advantages to the map approach.


This is the one paragraph I'm not sure I completely follow. derived-
args is a pretty dumb (as in intelligence) function. It just takes the
core args (the ones passed in by the user) and augments them with some
convenience values that are static for the whole run of the
calculator.

So without the map top level functions like Rent, Sell,
MonthlyRentalProfit, etc. would literally need to take 30+ arguments
(I'm not exaggerating btw). My root function looks like:

(defn run-calculator
   [args]
   (let [derived-args (derived-args args)]
(- (rent derived-args) (sell derived-args

I have to think that's preferable to submitting 30+ arguments to rent
and sell.

Or were you suggesting a different approach?

 Looking good!

 -R

   Mega 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
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: newbie question: Please help me stop creating constructors

2010-02-19 Thread Richard Newman

I have to think that's preferable to submitting 30+ arguments to rent
and sell.

Or were you suggesting a different approach?


The different approach only works with a different approach :)

The way you've structured run-calculator, using the map is best,  
because 30 arguments is crazy.


Your need to pass 30 arguments to rent and sell because they need to  
obtain or compute all of their intermediate values. You have a tree,  
with rent and sell doing all the work.


The alternative approach is to make your functions take the  
intermediate values as arguments explicitly, and define those  
functions much like your equations. You then bind the intermediate  
values in a let... perhaps best shown by example. Instead of


(defn house-depreciation
	The amount of depreciation that can be claimed on Federal Income  
Taxes in year y

[y args]
{:pre [(valid-year? y args)]}
(cond
( y 27) 0
( y 27) (/ (house-sales-price 0 args) 27.5)
(= y 27) (* 0.5 (/ (house-sales-price 0 args) 27.5

you would write

(defn house-depreciation
	The amount of depreciation that can be claimed on Federal Income  
Taxes in year y

[y house-sale-price]
{:pre [(valid-year? y args)]}
(cond
( y 27) 0
( y 27) (/ house-sale-price 27.5)
(= y 27) (* 0.5 (/ house-sale-price 27.5


This transformation applies to all of your functions, so even rent and  
sell get defined in terms of their intermediate values, just as I  
showed in a much earlier email.


Your calculator would become

(defn run-calculator
  [args]
  (let [...
house-sale-price (some-fn ... some-arg)
...
house-depreciation (house-depreciation y house-sale-price)
...
sell-value (sell house-sale-profit-0 rmoc mib)
...]
   (- rent sell)))

This way your individual functions become really simple, expressed in  
terms of
their direct named inputs and outputs only, just like your PDF's  
equations. Your
calculator function becomes the place where the web of interconnected  
values is

realized through a sequence of intermediate values.

You can easily test each individual function, just as you can now,  
only without

the overhead and syntax of those extra maps (which carry a ton of extra
values and obscure what's happening). Individual functions are less  
likely to
recompute redundant values (I'm sure rent and sell both involve some  
common
terms), and that avoidance doesn't involve jamming intermediate values  
into the

argument map.

More interestingly, this means you can build calculators for different  
things
(maybe comparing the tax advantages of different mortgages and  
depreciation
tricks...) by using the same functions. I don't know if that's  
possible with

the map approach as you've written it.

What you've done with the argument map approach is essentially to use  
a map as

an object: the map is a bunch of fields, your derived-args function is a
constructor (which sets up the derived members), and your individual  
functions

are methods on that object. It's OO with a mask.

Now, OO is sometimes the right way to do things, but if you really  
want to see
whether a more functional approach has advantages in this situation,  
you should

consider whether you can invert things a little.

Just a thought.

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


Re: newbie question: Please help me stop creating constructors

2010-02-18 Thread John Williams
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.comclojure%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

Re: newbie question: Please help me stop creating constructors

2010-02-18 Thread Yaron
Way back when I was a wee lad I had been taught that a thunk is any
function that takes no arguments. My definition for my derived values
never took any arguments because they exclusively relied on global
variables.

For example:

(defn months_actively_renting
The number of months during the time we are in the rental business
that we are either trying to rent the house out or have rented it out
[]
(* (+ *Months_To_Find_Tenant* *Months_In_Lease*) *Lease_Cycles*))

That's all I meant by the term thunk.

On Feb 17, 10:20 pm, Richard Newman holyg...@gmail.com wrote:
  I'm just trying to figure out what the right pattern is
  because the fact that I'm forced to make the derived values into
  thunks feels really wrong but I honestly don't know what's right in
  the context of Clojure.

 I don't think you're using the term thunk correctly.

 A thunk is (usually) a no-argument function, typically used for things  
 like delayed evaluation, and typically capturing some environment. E.g.,

 (defn hello [thunk]
    (println Hello,  (thunk)))

 (defn make-name-thunk [name]
    (fn [] name))

 (let [n (make-name-thunk Jim)]
    (println Calling hello...)
    (hello n))

 You are not making your derived values into thunks by this definition.  
 Your derived values are just that: values, computed by functions.  
 Compute them when you need them by invoking the appropriate functions  
 with the appropriate arguments.

 Can you explain what you mean by thunk?

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


Re: newbie question: Please help me stop creating constructors

2010-02-18 Thread Yaron
I spent a bunch of time reading and re-reading your mails.

Michal Marczyk's mail (which I read every line of, thank you for
taking the time to write it) was the one that made me get what
Richard Newman has with utmost patience (THANK YOU!), I believe,
been trying to gently beat into my head from the start.

Richard, your mails were extremely clear (and at this point I've read
them all at least 2 or 3 times) but my head was so far away from the
problem space that I needed a sufficient amount of beating before I
could finally even begin to grok anything. It took me forever to get
over the idea that I needed global variables. It was a stupid idee
fixe on my part.

I just took a piece of my code and re-worked it and made it available
at http://www.goland.org/rent_or_sell_refactor.clj.

My approach is as follows:

#1 - I removed all globally scoped defs (well, I left one, but it's
Months-In-Year and is just there for readability purposes). And per
Jarkko Oranen's mail I fixed the dashes. :)

#2 - I created a function called derived-args. It takes as input a map
that is to contain all the arguments provided by the user. It then
adds to that map all the derived values. This means that the derived
values get calculated exactly one time. It is the output of derived-
args that will be put at the very top of the function chain and passed
on down.

#3 - For some functions I explicitly just list out the arguments they
need. But I made a conscious decision not to do that in all cases. I
have a number of functions that I call a lot and constantly having to
break out their arguments when I call them would quickly grow tedious.
So instead I pass those functions the args map and then let them use
keys to break out the values. Probably the most egregious example of
this pattern is valid-month? I use this in preconditions all over the
place. So rather than passing its second argument, months-in-business,
as a separate argument I just pass in the whole args map and break out
the value inside of valid-month? The benefit of this approach is that
all the functions that call valid-month don't themselves have to break
out months-in-business in their keys, they can just pass in args.

Does http://www.goland.org/rent_or_sell_refactor.clj work more or less
the way y'all have been suggesting? In other words have I finally
created something that is heading in the 'right' direction? I realize
you can't properly judge it until I'm done but I wanted to find out if
I was roughly heading in the right direction.

   Thanks

 Yaron

On Feb 17, 10:36 pm, Richard Newman holyg...@gmail.com wrote:
  I don't expect anyone to actually read, rather I was hoping some folks
  who know Clojure might just glance at it to get the rhythm of the
  math. It's the pattern, not the detail that matters. How should what
  is essentially a monster algebra equation be codified in Clojure?

 I looked at your PDF.

 You express the equations as functions. Turning your equation notation  
 into function notation -- I'll use Haskell's as an example:

 OpportunityCost = Rent - Sell

 becomes

 opportunityCost r s = r - s

 or in Clojure:

 (defn opportunity-cost [r s]
(- r s))

 Note that the implicit arguments in your equational notation become  
 explicit arguments in the functional version.

 How do I compute r and s? Why, with functions of course! Let's take  
 Sell as an example.

 Sell = HouseSaleProfit0(1 +  
 RealMonthlyOpportunityCost)^MonthsInBusiness

 which becomes

 (defn sell [hsp-zero rmoc mib]
(* hsp-zero
   (exp (+ 1 rmoc) mib))); Assuming exp defined.

 Now, assuming that we have Rent, HSP0, RMOC, and MIB calculated (which  
 follows the same pattern), we compute our OpportunityCost:

 (defn -main []
   ;; TODO: extract user arguments.
   ;; ...
   (let [hsp-zero (...)   ; More calculation.
  rmoc (...)
 mib (...)]
 (println Opportunity Cost: 
   (opportunity-cost rent (sell hsp-zero rmoc mib

 To turn this into your final code, you need only:

 * Keep walking through your formulae until you've expressed everything  
 as functions;
 * Grab the nineteen or so leaf values you need from the user, and  
 plug them into your calls.

 When you have intermediate values, bind them with let, as I show above.

 Note that:

 * Each of the functions stands alone, defined in terms of its  
 arguments, and follows naturally from your equations
 * You can compute any intermediate stage, and print them out, log  
 them, whatever
 * There are no global values or bindings
 * You can name each intermediate value using let; your main function  
 can essentially be a sequential set of intermediate calculations, just  
 like your PDF.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to 

Re: newbie question: Please help me stop creating constructors

2010-02-18 Thread Richard Newman

Richard Newman has with utmost patience (THANK YOU!), I believe,
been trying to gently beat into my head from the start.


No problem. Happy to help.



Richard, your mails were extremely clear (and at this point I've read
them all at least 2 or 3 times) but my head was so far away from the
problem space that I needed a sufficient amount of beating before I
could finally even begin to grok anything. It took me forever to get
over the idea that I needed global variables. It was a stupid idee
fixe on my part.


These things take time! Props for not giving up in disgust :)



I just took a piece of my code and re-worked it and made it available
at http://www.goland.org/rent_or_sell_refactor.clj.


Looks pretty good to me. I like your use of preconditions and the  
number of tests. I think your indentation is a little deep (I go for  
two spaces, myself), and I never use :Capital keywords, but otherwise  
great.


You might be interested in the `are` macro to make your test code  
simpler:


user= (doc are)
-
clojure.test/are
([argv expr  args])
Macro
  Checks multiple assertions with a template expression.
  See clojure.template/do-template for an explanation of
  templates.

  Example: (are [x y] (= x y)
2 (+ 1 1)
4 (* 2 2))
  Expands to:
   (do (is (= 2 (+ 1 1)))
   (is (= 4 (* 2 2



#2 - I created a function called derived-args. It takes as input a map
that is to contain all the arguments provided by the user. It then
adds to that map all the derived values. This means that the derived
values get calculated exactly one time. It is the output of derived-
args that will be put at the very top of the function chain and passed
on down.


That seems like a reasonable approach.


Does http://www.goland.org/rent_or_sell_refactor.clj work more or less
the way y'all have been suggesting? In other words have I finally
created something that is heading in the 'right' direction? I realize
you can't properly judge it until I'm done but I wanted to find out if
I was roughly heading in the right direction.


Pretty much!

One suggestion:

Rather than having two phases of derived args, and calling functions  
with arguments like:


 (total-house-depreciation args-and-mib)

I'd save that step and adjust total-house-depreciation, year-sold,  
etc. to take an additional months-in-business argument:


(defn total-house-depreciation
   The total amount of depreciation on the rental property taken  
over the period we were in business

   [args months-in-business]
   ...)

Then you can change your derived-args function to:

(defn derived-args
	[{:keys [months-to-find-tenant months-in-lease lease-cycles months-to- 
sell] :as args}]

  (assoc args
:months-in-business (months-in-business months-to-find-tenant  
months-in-lease lease-cycles months-to-sell)
:total-house-depreciation (total-house-depreciation args months- 
in-business)

:year-sold (year-sold args months-in-business)
:months-actively-renting (months-actively-renting months-to-find- 
tenant months-in-lease lease-cycles)))


No lets at all.
You'll see then that it's a small step from there to my suggested  
functional end game, which eliminates the passing of the args map  
altogether: derived-args would extract all the named arguments and  
pass just the specific ones to each function. No big deal, though;  
there are advantages to the map approach.


Looking good!

-R

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread CuppoJava
Hi Yaron,
Have you considered my example yet? It seems to fulfill your
requirements. One of the primary use-cases of (binding) is to avoid
bloating the parameter list of a group of functions.

If my example does not satisfy your needs, then I think we may have
all misunderstood what it is you're looking for. Something that you
could do to get your point across is to post some Java code that
illustrates the sort of abstraction that you're looking for.

  -Patrick

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Yaron
I did but it requires two levels of macro and that made me nervous.
The problem is derived values. When defining a binding, near as I can
tell, the values in the binding cannot see other values in the
binding. In other words:

(def *A* 10)
(binding [*A* 3 B (+ foo 1)] B)

Returns 11, not 4.

So to use the macro I have to:

(def *A* bogus_value)
(def B bogus_value)

(defmacro in-environment [env  body]
  `(binding [*A* :A ..]
(binding [B (+ *A* 1)...]
 ~...@body))

I think this would actually work. But it requires a bunch of
accounting (all the bogus global defs) and introduces some worrisome
ordering issues. For example, let's say I have a value C whose
definition is (def C (+ B 1)). I can't define it using the previous
macro. Because, again, bindings can't see each other. So now I'd have
to write a macro that dynamically created a whole set of nested
bindings. Which seems like a lot of work.

In other words:

(binding [*A* :A...]
  (binding [B (+ *A* 1)...]
   (binding [C (+ *B* 1)...]
 etc.

And I can't use let (which does allow for internal visibility) because
then other functions I call will bind to the global value not the let
value.

   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
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Yaron
I actually started off doing exactly what you suggested. The original
version of my program used a map for the arguments and then used
explicit arguments when the number of arguments fell to a reasonable
level.

For example, I started off with:

(defn months_in_business
The total number of months we will be in the business of renting out
our home
[Months_To_Find_Tenant Months_In_Lease Lease_Cycles Months_To_Sell]
(- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
Months_To_Sell)))

Which got called as (months_in_business Months_To_Find_Tenant
Months_In_Lease Lease_Cycles Months_To_Sell)

But this was a lot of typing every time I wanted to call the function.
So I changed it to:

(defn months_in_business
The total number of months we will be in the business of renting out
our home
[:keys [Months_To_Find_Tenant Months_In_Lease Lease_Cycles
Months_To_Sell]]
(- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
Months_To_Sell)))

Which got called as (months_in_business bag_o_args)

This at least meant less typing when calling the function but defining
the function still required a bunch of typing.

So eventually I just went to:

(defn months_in_business
The total number of months we will be in the business of renting out
our home
[]
(- (+ *Months_To_Find_Tenant* *Months_In_Lease*) (* *Lease_Cycles*)
(+ *Months_To_Sell*)))

Which was called as: (months_in_business)

At least there wasn't much typing involved but now I had a bunch of
thunks running around. Which is what brought me to the group in the
first place.

It seems to me that there is a design principal here somewhere that
says something like One shouldn't have to pass static values around
as arguments to functions. But because there is nothing like an
object context in Clojure this ended up meaning that derived values
like months_in_business have to be thunks. Which I though was
inelegant.

If, on the other hand, I was implementing this in an object oriented
language I would just say:

class foo
 var A
 var B
  foo (bag_o_args)
 {
A = (bag_o_args A)
B = A+1
 }

And I would be done. No heaps of typing. No thunks. Just what looks to
me like a nice simple solution.

But I recognize that I'm just running home to mommy because my
background is OO. That's why I came to the group in the first place.
Since I know I'm blinded by my OO past I wanted to see if there was an
approach to the problem in Clojure that was as easy and straight
forward as what I would have done in an OO language.

That having been said, defining a bunch of thunks isn't the worst
thing in the world. But it is unfortunate from both a design and
performance perspective.

Yaron

On Feb 16, 11:07 pm, Richard Newman holyg...@gmail.com wrote:
  It seems however that the consensus of the group based on what I've
  said so far is to pass around state in a structmap.

 Not necessarily a struct-map. Just a map.

  This is nice in
  that it makes each function completely self contained (e.g. no
  external references). It's unfortunate in that it now means that every
  single function needs this extra argument and every variable access
  either needs to use the :keys feature in the arguments or has to
  directly refer to the keys in the map.

 Not necessarily. At some point your functions should be fine-grained  
 enough that they only take a couple of arguments. As soon as you drop  
 below 6 or 7, where they're all mandatory, switch to ordinary function  
 argument style.

 Wherever you call those functions should do the unpacking.

 E.g.,

 (defn outer-1 [{:keys [foo bar baz noo]}]
    (let [interm (foo-bar foo bar)
          fiddle (frostrup baz noo)]
      (tweep interm fiddle)))

 After all, your house-sale-profit function should be expressed in  
 terms of two arguments:

 (defn house-sale-profit [house-sale-price house-sale-expenses]
    ...)

 It doesn't care about the other 17.

 Another thing: that big entry point function is like a much tidier  
 version of the Java constructor that you created with 19 arguments --  
 tidier in that you can use named keys or a map to identify the  
 arguments.

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Yaron
I actually started off doing exactly what you suggested. The original
version of my program used a map for the arguments and then used
explicit arguments when the number of arguments fell to a reasonable
level.

For example, I started off with:

(defn months_in_business
The total number of months we will be in the business of renting out
our home
[Months_To_Find_Tenant Months_In_Lease Lease_Cycles Months_To_Sell]
(- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
Months_To_Sell)))

Which got called as (months_in_business Months_To_Find_Tenant
Months_In_Lease Lease_Cycles Months_To_Sell)

But this was a lot of typing every time I wanted to call the function.
So I changed it to:

(defn months_in_business
The total number of months we will be in the business of renting out
our home
[:keys [Months_To_Find_Tenant Months_In_Lease Lease_Cycles
Months_To_Sell]]
(- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
Months_To_Sell)))

Which got called as (months_in_business bag_o_args)

This at least meant less typing when calling the function but defining
the function still required a bunch of typing.

So eventually I just went to:

(defn months_in_business
The total number of months we will be in the business of renting out
our home
[]
(- (+ *Months_To_Find_Tenant* *Months_In_Lease*) (* *Lease_Cycles*)
(+ *Months_To_Sell*)))

Which was called as: (months_in_business)

At least there wasn't much typing involved but now I had a bunch of
thunks running around. Which is what brought me to the group in the
first place.

It seems to me that there is a design principal here somewhere that
says something like One shouldn't have to pass static values around
as arguments to functions. But because there is nothing like an
object context in Clojure this ended up meaning that derived values
like months_in_business have to be thunks. Which I though was
inelegant.

If, on the other hand, I was implementing this in an object oriented
language I would just say:

class foo
 var A
 var B
  foo (bag_o_args)
 {
A = (bag_o_args A)
B = A+1
 }

And I would be done. No heaps of typing. No thunks. Just what looks to
me like a nice simple solution.

But I recognize that I'm just running home to mommy because my
background is OO. That's why I came to the group in the first place.
Since I know I'm blinded by my OO past I wanted to see if there was an
approach to the problem in Clojure that was as easy and straight
forward as what I would have done in an OO language.

That having been said, defining a bunch of thunks isn't the worst
thing in the world. But it is unfortunate from both a design and
performance perspective.

Yaron

On Feb 16, 11:07 pm, Richard Newman holyg...@gmail.com wrote:
  It seems however that the consensus of the group based on what I've
  said so far is to pass around state in a structmap.

 Not necessarily a struct-map. Just a map.

  This is nice in
  that it makes each function completely self contained (e.g. no
  external references). It's unfortunate in that it now means that every
  single function needs this extra argument and every variable access
  either needs to use the :keys feature in the arguments or has to
  directly refer to the keys in the map.

 Not necessarily. At some point your functions should be fine-grained  
 enough that they only take a couple of arguments. As soon as you drop  
 below 6 or 7, where they're all mandatory, switch to ordinary function  
 argument style.

 Wherever you call those functions should do the unpacking.

 E.g.,

 (defn outer-1 [{:keys [foo bar baz noo]}]
    (let [interm (foo-bar foo bar)
          fiddle (frostrup baz noo)]
      (tweep interm fiddle)))

 After all, your house-sale-profit function should be expressed in  
 terms of two arguments:

 (defn house-sale-profit [house-sale-price house-sale-expenses]
    ...)

 It doesn't care about the other 17.

 Another thing: that big entry point function is like a much tidier  
 version of the Java constructor that you created with 19 arguments --  
 tidier in that you can use named keys or a map to identify the  
 arguments.

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread CuppoJava
Hi Yaron,

You've slightly misunderstood my suggestion. I hope this will shed
some reasoning on it:

In OO, what you are effectively doing is this:

The Object represents the environment under which you do your
calculations.
The environment object is created by your constructor.
Once this environment has been created, you can use it to do
calculations using foo.tax_deductible_expenses(1).

My example is meant to capture this style of programming. (Whether
this style is appropriate is up to you to decide.)

The environment is represented by a map.
You can write a function that creates an environment just like how
you can write a constructor to create an environment object in Java.
  eg.  new-environment( ... )
Once this environment has been created, you may use it to do
calculations using
  (in-environment foo
 (tax-deductible-expenses 1))

The in-environment macro is not meant to contain any logic. It is
solely meant to save you some typing.

Hope that's more clear.
  -Patrick

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread CuppoJava
I think it will help you get used to Clojure by spending some time to
  program in the most straight-forward way possible.

Sometimes it's really helpful to just learn from a blank-slate instead
of trying to find analogies to Java.
  -Patrick

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Tom Faulhaber
You can combine let and binding like this to make this slightly more
elegant:

(let [a# 'expr involving *A* *B* and *C*''
  b# 'expr involving *A* *B* and *C*''
  c# 'expr involving *A* *B* and *C*'']
  (binding [*A* a#
   *B* b#
   *C* c#]
 ...))

Note the x# form which does an implicit gensym for you so you get
unique names.

This at least reduces it from n levels to two levels. It would be
pretty easy to build a parallel-binding macro that did this for you.

hth,

Tom


On Feb 17, 10:09 am, Yaron ygol...@gmail.com wrote:
 I did but it requires two levels of macro and that made me nervous.
 The problem is derived values. When defining a binding, near as I can
 tell, the values in the binding cannot see other values in the
 binding. In other words:

 (def *A* 10)
 (binding [*A* 3 B (+ foo 1)] B)

 Returns 11, not 4.

 So to use the macro I have to:

 (def *A* bogus_value)
 (def B bogus_value)

 (defmacro in-environment [env  body]
   `(binding [*A* :A ..]
     (binding [B (+ *A* 1)...]
     �...@body))

 I think this would actually work. But it requires a bunch of
 accounting (all the bogus global defs) and introduces some worrisome
 ordering issues. For example, let's say I have a value C whose
 definition is (def C (+ B 1)). I can't define it using the previous
 macro. Because, again, bindings can't see each other. So now I'd have
 to write a macro that dynamically created a whole set of nested
 bindings. Which seems like a lot of work.

 In other words:

 (binding [*A* :A...]
   (binding [B (+ *A* 1)...]
    (binding [C (+ *B* 1)...]
      etc.

 And I can't use let (which does allow for internal visibility) because
 then other functions I call will bind to the global value not the let
 value.

    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
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread David Nolen
(defn months_in_business
   The total number of months we will be in the business of renting out
our home
   [:keys [Months_To_Find_Tenant Months_In_Lease Lease_Cycles
Months_To_Sell]]
   (- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
Months_To_Sell)))

-

I have no idea why you want to type this much:

(defn months-in-business
  [:keys [mtft mil lc mts]
  (- (+ mtft mil) (* lc) (+ mts))

But how do we know what these abbreviations mean while we develop our
application? Write a couple of helper functions:

(defn map-to-humane-repr [m]
 (let [ok (keys m)
   vs (vals m)]
   (zipmap (map mappings ok) vs)))

(def *dummy*
 {:mtft 1,
  :mil 24,
  :lc 5,
  :mts 12})

(map-to-humane-repr *dummy*) -

{Months to Sell 12,
 Lease Cycles 5,
 Months In Lease 24,
 Months To Find Tenant 1}

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

Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Laurent PETIT
Hello,

2010/2/17 Yaron ygol...@gmail.com:
 I actually started off doing exactly what you suggested. The original
 version of my program used a map for the arguments and then used
 explicit arguments when the number of arguments fell to a reasonable
 level.

 For example, I started off with:

 (defn months_in_business
        The total number of months we will be in the business of renting out
 our home
        [Months_To_Find_Tenant Months_In_Lease Lease_Cycles Months_To_Sell]
        (- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
 Months_To_Sell)))

 Which got called as (months_in_business Months_To_Find_Tenant
 Months_In_Lease Lease_Cycles Months_To_Sell)

 But this was a lot of typing every time I wanted to call the function.
 So I changed it to:

 (defn months_in_business
        The total number of months we will be in the business of renting out
 our home
        [:keys [Months_To_Find_Tenant Months_In_Lease Lease_Cycles
 Months_To_Sell]]
        (- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
 Months_To_Sell)))

 Which got called as (months_in_business bag_o_args)

 This at least meant less typing when calling the function but defining
 the function still required a bunch of typing.

 So eventually I just went to:

 (defn months_in_business
        The total number of months we will be in the business of renting out
 our home
        []
        (- (+ *Months_To_Find_Tenant* *Months_In_Lease*) (* *Lease_Cycles*)
 (+ *Months_To_Sell*)))

 Which was called as: (months_in_business)

 At least there wasn't much typing involved but now I had a bunch of
 thunks running around. Which is what brought me to the group in the
 first place.

 It seems to me that there is a design principal here somewhere that
 says something like One shouldn't have to pass static values around
 as arguments to functions. But because there is nothing like an
 object context in Clojure this ended up meaning that derived values
 like months_in_business have to be thunks. Which I though was
 inelegant.

 If, on the other hand, I was implementing this in an object oriented
 language I would just say:

 class foo
  var A
  var B
  foo (bag_o_args)
  {
    A = (bag_o_args A)
    B = A+1
  }

I would like to try to help, but I first need to understand your
(pseudo?) OO langage above.
Could you detail it a little bit more ?


 And I would be done. No heaps of typing. No thunks. Just what looks to
 me like a nice simple solution.

 But I recognize that I'm just running home to mommy because my
 background is OO. That's why I came to the group in the first place.
 Since I know I'm blinded by my OO past I wanted to see if there was an
 approach to the problem in Clojure that was as easy and straight
 forward as what I would have done in an OO language.

 That having been said, defining a bunch of thunks isn't the worst
 thing in the world. But it is unfortunate from both a design and
 performance perspective.

    Yaron

 On Feb 16, 11:07 pm, Richard Newman holyg...@gmail.com wrote:
  It seems however that the consensus of the group based on what I've
  said so far is to pass around state in a structmap.

 Not necessarily a struct-map. Just a map.

  This is nice in
  that it makes each function completely self contained (e.g. no
  external references). It's unfortunate in that it now means that every
  single function needs this extra argument and every variable access
  either needs to use the :keys feature in the arguments or has to
  directly refer to the keys in the map.

 Not necessarily. At some point your functions should be fine-grained
 enough that they only take a couple of arguments. As soon as you drop
 below 6 or 7, where they're all mandatory, switch to ordinary function
 argument style.

 Wherever you call those functions should do the unpacking.

 E.g.,

 (defn outer-1 [{:keys [foo bar baz noo]}]
    (let [interm (foo-bar foo bar)
          fiddle (frostrup baz noo)]
      (tweep interm fiddle)))

 After all, your house-sale-profit function should be expressed in
 terms of two arguments:

 (defn house-sale-profit [house-sale-price house-sale-expenses]
    ...)

 It doesn't care about the other 17.

 Another thing: that big entry point function is like a much tidier
 version of the Java constructor that you created with 19 arguments --
 tidier in that you can use named keys or a map to identify the
 arguments.

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

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

Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Michał Marczyk
I must say that I find Richard's suggestions to be very reasonable,
but I'd like to add my own take... This is meant as a step-by-step
account of my thinking process, so it starts out with a statement of
the basics. Skim  skip if you prefer.

The problem to be solved is basically a huge calculation. When written
out -- for the purpose of defining the problem -- in the usual
mathematical notation, it turns out to depend on multiple free
variables (inflation rate, interest on the mortgage etc.); then
there's a bunch of named parameters / dependent variables whose values
are derived from those free variables.

So, the natural thing to do is what you do in that .pdf you posted:
you break it down into a bunch of equations defining the dependent
variables in the above in terms of the free variables and / or
previously defined dependent variables plus one inequality of the
form, say, rent-profit = sale-profit, whose truth or falsity is to be
established.

Now, an imperative programme to calculate whether rent-profit does or
does not exceed sale-profit would proceed as follows:

free-variable-1 = some-value-1
free-variable-2 = some-value-2
...
dependent-variable-1 = some-function-of(free-variable-k,
free-variable-l, free-variable-n)
...
answer = rent-profit-function(...some-arguments...) =
sale-profit-function(...some-arguments...)

A functional programme, on the other hand, would contain no section to
correspond to the free-variable-n assignments at all. Then in place of
all the dependent-variable-m assignments it would contain function
definitions:

(defn calculate-dependent-variable-1 [free-var-k, free-var-l ...]
  ...)

When you start composing those, you do things like

(defn calculate-problematic-quantity [...all free vars needed in side...]
  (let [dep-var-1 (calculate-dependent-variable-1 ...the arguments...)
dep-var-2 (calculate-dependent-variable-2 ...the arguments...)
...]
...combine the free-vars received as arguments
with the dep-vars calculated in the bindings portion of the
let form to produce the return value...))

Feel free to receive dependent variables as arguments if you're likely
to have multiple functions depend on them in some way:

(defn f1 [dep-var-1 ...] ...)
(defn f2 [dep-var-1 ...] ...)
(defn function-using-f1-f2 [...args...]
  (let [dep-var-1 (calculate-dependent-variable-1 ...args...)
 f1-val (f1 dep-var-1 ...)
 f2-val (f2 dep-var-1 ...)
...))

Then once you do have all the building blocks in place, you'd write
one monster entry function taking some values for the free variables
-- perhaps in the form of a map -- and have it call the
building-block-functions, perhaps using the sequential binding
facitility of the let special form to name intermediate values for use
in further computational steps.

This process strikes me as incredibly similar to what you would do if
you were to solve the equations by hand: you break them down into
well-defined intermediate steps, write down recipes defining the exact
nature of those steps, then write down formulae combining the results
of those intermediate steps. You strive to reduce the number of free
variables any single equation depends on, preferring to break down
huge equations into smaller ones which depend on parameters defined by
further small equations. Etc.

In Haskell you can even write the main equations on top, followed by
the helper equations lower down, possibly limiting the scope of the
latter:

calculateFoo x y z = fooComponent1 + fooComponent2
  where
fooComponent1 = (some expression in x, y, z)
fooComponent2 = (some expression in x, y, z)

In Clojure you'd use a let form for that, which may be a blessing or a
curse both syntactically (the issue of what you put on the top) and
semantically (because where and let bindings are mutually
recursive in Haskell). The basic idea stays the same, though, with
Haskell's syntax perhaps making it slightly more obvious how the
Haskell functions involved are almost direct transliterations of the
mathematical, purely declarative statements of the nature of the
calculational subproblems. That syntax is something you'd actually
have to learn the (considerable) quirks of, so some find the Lisp
syntax-less approach ultimately more manageable (myself included).

Anyway, I'd say that your project is the perfect dream use case for
functional programming... I wonder if I've managed to expose some of
my reasons for feeling this way? :-)

An additional note: given the purpose of the calculations involved, I
guess you'll want to be well-assured of the correctness of the result.
Using maps to pass around named values may help with that; I'd even go
as far as using assertions and / or preconditions to make sure that
each function does receive all the values it expects in its argument
map.

What I *would not* do, however, is to mass around one huge map all the
time; I'd still only give each function the exact arguments it must
receive, putting them in a 

Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Yaron
I think I see what you're saying. But honestly my goal isn't to
replicate the OO experience. My goal is to replicate how easy OO made
this specific scenario. In other words I want to use Clojure properly
and trying to paste an OO framework on Clojure has got to be a major
anti-pattern. I'm just trying to figure out what the right pattern is
because the fact that I'm forced to make the derived values into
thunks feels really wrong but I honestly don't know what's right in
the context of Clojure.

On Feb 17, 10:39 am, CuppoJava patrickli_2...@hotmail.com wrote:
 HiYaron,

 You've slightly misunderstood my suggestion. I hope this will shed
 some reasoning on it:

 In OO, what you are effectively doing is this:

 The Object represents the environment under which you do your
 calculations.
 The environment object is created by your constructor.
 Once this environment has been created, you can use it to do
 calculations using foo.tax_deductible_expenses(1).

 My example is meant to capture this style of programming. (Whether
 this style is appropriate is up to you to decide.)

 The environment is represented by a map.
 You can write a function that creates an environment just like how
 you can write a constructor to create an environment object in Java.
   eg.  new-environment( ... )
 Once this environment has been created, you may use it to do
 calculations using
   (in-environment foo
      (tax-deductible-expenses 1))

 The in-environment macro is not meant to contain any logic. It is
 solely meant to save you some typing.

 Hope that's more clear.
   -Patrick

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Yaron
The reason for typing so much is maintainability. I'll have to come
back to this code again and again over a period of years and there's
no chance in heck I'll remember anything I did before. So I've learned
that using clearer variable names, even with a little extra typing, is
a price worth paying.

On Feb 17, 10:46 am, David Nolen dnolen.li...@gmail.com wrote:
 (defn months_in_business
        The total number of months we will be in the business of renting out
 our home
        [:keys [Months_To_Find_Tenant Months_In_Lease Lease_Cycles
 Months_To_Sell]]
        (- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
 Months_To_Sell)))

 -

 I have no idea why you want to type this much:

 (defn months-in-business
   [:keys [mtft mil lc mts]
   (- (+ mtft mil) (* lc) (+ mts))

 But how do we know what these abbreviations mean while we develop our
 application? Write a couple of helper functions:

 (defn map-to-humane-repr [m]
      (let [ok (keys m)
            vs (vals m)]
        (zipmap (map mappings ok) vs)))

 (def *dummy*
      {:mtft 1,
       :mil 24,
       :lc 5,
       :mts 12})

 (map-to-humane-repr *dummy*) -

 {Months to Sell 12,
  Lease Cycles 5,
  Months In Lease 24,
  Months To Find Tenant 1}

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Yaron
That's actually quite a nifty use of the fact that code/data is the
same in Clojure. But how do I test things out? In other words, how do
I make sure that the expression defining a# is correct? Especially
when any test has to itself be in the context of all the variables?

But more to the point I think there is a difference between possible
and desirable. You're giving me what I asked for, e.g. a way to
achieve my goal of not having the derived values be thunks. But I
can't help but think that I'm just approaching the whole problem in
the wrong way in Clojure. That's why I posted 
http://www.goland.org/sellorrent.pdf.

I don't expect anyone to actually read, rather I was hoping some folks
who know Clojure might just glance at it to get the rhythm of the
math. It's the pattern, not the detail that matters. How should what
is essentially a monster algebra equation be codified in Clojure?

On Feb 17, 10:48 am, Tom Faulhaber tomfaulha...@gmail.com wrote:
 You can combine let and binding like this to make this slightly more
 elegant:

 (let [a# 'expr involving *A* *B* and *C*''
       b# 'expr involving *A* *B* and *C*''
       c# 'expr involving *A* *B* and *C*'']
   (binding [*A* a#
                *B* b#
                *C* c#]
      ...))

 Note the x# form which does an implicit gensym for you so you get
 unique names.

 This at least reduces it from n levels to two levels. It would be
 pretty easy to build a parallel-binding macro that did this for you.

 hth,

 Tom

 On Feb 17, 10:09 am,Yaronygol...@gmail.com wrote:

  I did but it requires two levels of macro and that made me nervous.
  The problem is derived values. When defining a binding, near as I can
  tell, the values in the binding cannot see other values in the
  binding. In other words:

  (def *A* 10)
  (binding [*A* 3 B (+ foo 1)] B)

  Returns 11, not 4.

  So to use the macro I have to:

  (def *A* bogus_value)
  (def B bogus_value)

  (defmacro in-environment [env  body]
    `(binding [*A* :A ..]
      (binding [B (+ *A* 1)...]
      �...@body))

  I think this would actually work. But it requires a bunch of
  accounting (all the bogus global defs) and introduces some worrisome
  ordering issues. For example, let's say I have a value C whose
  definition is (def C (+ B 1)). I can't define it using the previous
  macro. Because, again, bindings can't see each other. So now I'd have
  to write a macro that dynamically created a whole set of nested
  bindings. Which seems like a lot of work.

  In other words:

  (binding [*A* :A...]
    (binding [B (+ *A* 1)...]
     (binding [C (+ *B* 1)...]
       etc.

  And I can't use let (which does allow for internal visibility) because
  then other functions I call will bind to the global value not the let
  value.

     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
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Richard Newman

I'm just trying to figure out what the right pattern is
because the fact that I'm forced to make the derived values into
thunks feels really wrong but I honestly don't know what's right in
the context of Clojure.


I don't think you're using the term thunk correctly.

A thunk is (usually) a no-argument function, typically used for things  
like delayed evaluation, and typically capturing some environment. E.g.,


(defn hello [thunk]
  (println Hello,  (thunk)))

(defn make-name-thunk [name]
  (fn [] name))

(let [n (make-name-thunk Jim)]
  (println Calling hello...)
  (hello n))

You are not making your derived values into thunks by this definition.  
Your derived values are just that: values, computed by functions.  
Compute them when you need them by invoking the appropriate functions  
with the appropriate arguments.


Can you explain what you mean by thunk?

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


Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Yaron
Absolutely. I typed up an example in Scala.

class RentOrSell(val Months_To_Find_Tenant: Int, val Months_In_Lease:
Int, val Lease_Cycles: Int, val Months_To_Sell: Int) {
  val months_in_business: Int = ((Months_To_Find_Tenant +
Months_In_Lease) * Lease_Cycles) + Months_To_Sell
}

When I create a class instance I pass in the user defined variables (I
only used 4 in this example). Those values are then bound as invariant
values and used to create months_in_business which is itself an
invariant value (e.g. bound at class creation time and then
immutable).

This is the effect I was expecting. That I could define both the user
supplied values and the derived values as immutable values. Instead I
had to create thunks for the derived values for the reasons previously
described.

But again I'm completely open to the idea that I'm just going about
this all wrong. I have spent more years of my life than I care to
remember writing OO code so I have no doubt I'm relying on instincts
that just don't apply here.

Ideally I'd love to figure out how to properly write a program that
implements http://www.goland.org/sellorrent.pdf in Clojure rather than
beat Clojure into looking like what I'm used to from my OO days. Put
another way, I speak Clojure with a really thick OO accent and I'd
like to learn better how to speak it like a native. :)

   Yaron

On Feb 17, 11:53 am, Laurent PETIT laurent.pe...@gmail.com wrote:
 Hello,

 2010/2/17Yaronygol...@gmail.com:



  I actually started off doing exactly what you suggested. The original
  version of my program used a map for the arguments and then used
  explicit arguments when the number of arguments fell to a reasonable
  level.

  For example, I started off with:

  (defn months_in_business
         The total number of months we will be in the business of renting out
  our home
         [Months_To_Find_Tenant Months_In_Lease Lease_Cycles Months_To_Sell]
         (- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
  Months_To_Sell)))

  Which got called as (months_in_business Months_To_Find_Tenant
  Months_In_Lease Lease_Cycles Months_To_Sell)

  But this was a lot of typing every time I wanted to call the function.
  So I changed it to:

  (defn months_in_business
         The total number of months we will be in the business of renting out
  our home
         [:keys [Months_To_Find_Tenant Months_In_Lease Lease_Cycles
  Months_To_Sell]]
         (- (+ Months_To_Find_Tenant Months_In_Lease) (* Lease_Cycles) (+
  Months_To_Sell)))

  Which got called as (months_in_business bag_o_args)

  This at least meant less typing when calling the function but defining
  the function still required a bunch of typing.

  So eventually I just went to:

  (defn months_in_business
         The total number of months we will be in the business of renting out
  our home
         []
         (- (+ *Months_To_Find_Tenant* *Months_In_Lease*) (* *Lease_Cycles*)
  (+ *Months_To_Sell*)))

  Which was called as: (months_in_business)

  At least there wasn't much typing involved but now I had a bunch of
  thunks running around. Which is what brought me to the group in the
  first place.

  It seems to me that there is a design principal here somewhere that
  says something like One shouldn't have to pass static values around
  as arguments to functions. But because there is nothing like an
  object context in Clojure this ended up meaning that derived values
  like months_in_business have to be thunks. Which I though was
  inelegant.

  If, on the other hand, I was implementing this in an object oriented
  language I would just say:

  class foo
   var A
   var B
   foo (bag_o_args)
   {
     A = (bag_o_args A)
     B = A+1
   }

 I would like to try to help, but I first need to understand your
 (pseudo?) OO langage above.
 Could you detail it a little bit more ?



  And I would be done. No heaps of typing. No thunks. Just what looks to
  me like a nice simple solution.

  But I recognize that I'm just running home to mommy because my
  background is OO. That's why I came to the group in the first place.
  Since I know I'm blinded by my OO past I wanted to see if there was an
  approach to the problem in Clojure that was as easy and straight
  forward as what I would have done in an OO language.

  That having been said, defining a bunch of thunks isn't the worst
  thing in the world. But it is unfortunate from both a design and
  performance perspective.

     Yaron

  On Feb 16, 11:07 pm, Richard Newman holyg...@gmail.com wrote:
   It seems however that the consensus of the group based on what I've
   said so far is to pass around state in a structmap.

  Not necessarily a struct-map. Just a map.

   This is nice in
   that it makes each function completely self contained (e.g. no
   external references). It's unfortunate in that it now means that every
   single function needs this extra argument and every variable access
   either needs to use the :keys feature in the arguments or 

Re: newbie question: Please help me stop creating constructors

2010-02-17 Thread Richard Newman

I don't expect anyone to actually read, rather I was hoping some folks
who know Clojure might just glance at it to get the rhythm of the
math. It's the pattern, not the detail that matters. How should what
is essentially a monster algebra equation be codified in Clojure?


I looked at your PDF.

You express the equations as functions. Turning your equation notation  
into function notation -- I'll use Haskell's as an example:


OpportunityCost = Rent - Sell

becomes

opportunityCost r s = r - s

or in Clojure:

(defn opportunity-cost [r s]
  (- r s))

Note that the implicit arguments in your equational notation become  
explicit arguments in the functional version.


How do I compute r and s? Why, with functions of course! Let's take  
Sell as an example.


	Sell = HouseSaleProfit0(1 +  
RealMonthlyOpportunityCost)^MonthsInBusiness


which becomes

(defn sell [hsp-zero rmoc mib]
  (* hsp-zero
 (exp (+ 1 rmoc) mib))); Assuming exp defined.


Now, assuming that we have Rent, HSP0, RMOC, and MIB calculated (which  
follows the same pattern), we compute our OpportunityCost:


(defn -main []
  ;; TODO: extract user arguments.
  ;; ...
  (let [hsp-zero (...)   ; More calculation.
rmoc (...)
mib (...)]
(println Opportunity Cost: 
 (opportunity-cost rent (sell hsp-zero rmoc mib


To turn this into your final code, you need only:

* Keep walking through your formulae until you've expressed everything  
as functions;
* Grab the nineteen or so leaf values you need from the user, and  
plug them into your calls.


When you have intermediate values, bind them with let, as I show above.

Note that:

* Each of the functions stands alone, defined in terms of its  
arguments, and follows naturally from your equations
* You can compute any intermediate stage, and print them out, log  
them, whatever

* There are no global values or bindings
* You can name each intermediate value using let; your main function  
can essentially be a sequential set of intermediate calculations, just  
like your PDF.


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


Re: newbie question: Please help me stop creating constructors

2010-02-16 Thread Yaron
Sean and Richard perhaps I can address both of your mails in a single
go. Here is an example of one of the functions from my calculator:

(defn tax_deductible_expenses
The total expenses incurred in business month m that are deductible
from federal income tax
[m]
(let
[prepHouse (inflate *Prep_House_0* m)
 fixedMonthlyCost (if (= m (months_in_business)) 0
(fixed_monthly_cost m))]
(condp = (house_state m)
:ForLease (+ fixedMonthlyCost (if (= 
(month_in_rental_cycle m) 0)
prepHouse 0))
:Leased (+ fixedMonthlyCost (* (rental_income m) (+
*Management_Fee* (if (= (month_in_rental_cycle m)
*Months_To_Find_Tenant*) *Tenant_Finding_Fee* 0
:ForSale (+ fixedMonthlyCost (if (= m 
(months_actively_renting))
prepHouse 0))
:Sold (house_sales_expenses m

Right now the function takes a single argument, m which is the month
that tax deductible expenses are being calculated for. All the other
values it needs are constants (e.g. either values provided at the
start by the user or derived values).

Now please look at a test I wrote to make sure the function does what
I think it does:

(deftest tax_deductible_expenses_basic
  (binding
[*Months_To_Find_Tenant* 5
 *Months_In_Lease* 5
 *Lease_Cycles* 1
 *House_Sales_Price_0* 300
 *Monthly_Inflation_Rate* 0.002
 *Buying_Agent_Fee_Type* :Percentage
 *Buying_Agent_Fee_Number* 0.05
 *Selling_Agent_Fee_Type* :FlatFee
 *Selling_Agent_Fee_Number* 1000
 *Other_Sales_Fee_0* 100
 *Excise_Tax* 0.5
 *Original_Loan_Amount* 1
 *Monthly_Loan_Interest* (/ 0.05 12)
 *Months_In_Loan* (* 10 12)
 *Loan_Month_At_Start* 3
 *Prep_House_0* 100
 *Management_Fee* 2
 *Tenant_Finding_Fee* 0.5
 *Months_To_Sell* 3]
 (is (= (tax_deductible_expenses 0) (+ (fixed_monthly_cost 0)
100)))
 (is (= (tax_deductible_expenses 1) (fixed_monthly_cost 1)))
 (is (= (tax_deductible_expenses 5) (+ (fixed_monthly_cost 5) (*
(rental_income 5) 2.5
 (is (= (tax_deductible_expenses 7) (+ (fixed_monthly_cost 7) (*
(rental_income 7) 2
 (is (= (tax_deductible_expenses 10) (+ (fixed_monthly_cost 10)
(inflate 100 10
 (is (= (tax_deductible_expenses 12) (fixed_monthly_cost 12)))
 (is (= (tax_deductible_expenses 13) (house_sales_expenses 13)

For the method tax_deductible_expenses to run it ends up requiring 19
user defined values. That's a whole lot of arguments to pass into a
function. Obviously I could wrap them up in a StructMap but then I get
expressions like (+ 1 (args :B)) which doesn't seem much better than
(+1 (B)).

The issue I'm really trying to put my finger on is - these arguments
really and truly are 'constants' within the context of the calculator.
But they are constants whose values are not known as compile time but
rather are known at run time. Does Clojure have a way to express a
'late bound' constant or is the 'right' solution to pass around 19+
arguments to functions or passing around StructMaps or making
everything into thunks?

   Thanks!

 Yaron

On Feb 15, 1:33 pm, Richard Newman holyg...@gmail.com wrote:
  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).

 In Java, everything's an object, so you go about this by defining some  
 class. All of its private members, its constructors, and its accessors  
 are there to support one thing: should I sell or rent my home?

 That is, rather than saying something like:

 should-i-sell given that:
    current-home-price = 100,000
    current-interest-rate = 5.2%
    ...

 you say

 HomeCalculator c = new HomeCalculator(10, 5.2, ...);
 boolean shouldSell = c.shouldSell();

 and the logic is tied up in the shouldSell method definition.

 When someone calls .setA(...), you have to recompute B, or you have to  
 make sure that B is dynamically computed in .getB().

 That's not how you do things in a functional programming language. You  
 don't define global variables B and A. Define functions that  
 compute things; thread them together; and then push your values in the  
 top.

 Start from the bottom up and the top down together; build a tree of  
 functions that compute what you want. For example, you might think  
 ah, I need to figure out my monthly payment on my mortgage. That's a  
 function of the initial principal, the term, and the rate:

 (defn monthly-payment [principal term-in-months interest-rate]
    ...)

 Then you want to figure out how much more or less you'll pay, assuming  
 a growth in rents of a certain percentage, over some number of months  
 spent living in the house. Let's start by computing a sequence of  
 rents, increasing over time:

 (defn monthly-rent [starting-value monthly-increase]
    (lazy-seq
      starting-value
      

Re: newbie question: Please help me stop creating constructors

2010-02-16 Thread Jarkko Oranen


On Feb 16, 8:27 pm, Yaron ygol...@gmail.com wrote:
 Sean and Richard perhaps I can address both of your mails in a single
 go. Here is an example of one of the functions from my calculator:

 (defn tax_deductible_expenses
         The total expenses incurred in business month m that are deductible
 from federal income tax
         [m]
         (let
                 [prepHouse (inflate *Prep_House_0* m)
                  fixedMonthlyCost (if (= m (months_in_business)) 0
 (fixed_monthly_cost m))]
                 (condp = (house_state m)
                         :ForLease (+ fixedMonthlyCost (if (= 
 (month_in_rental_cycle m) 0)
 prepHouse 0))
                         :Leased (+ fixedMonthlyCost (* (rental_income m) (+
 *Management_Fee* (if (= (month_in_rental_cycle m)
 *Months_To_Find_Tenant*) *Tenant_Finding_Fee* 0
                         :ForSale (+ fixedMonthlyCost (if (= m 
 (months_actively_renting))
 prepHouse 0))
                         :Sold (house_sales_expenses m

 Right now the function takes a single argument, m which is the month
 that tax deductible expenses are being calculated for. All the other
 values it needs are constants (e.g. either values provided at the
 start by the user or derived values).

First, a style nitpick: use foo-bar instead of fooBar or foo_bar
secondly, yes, you really should pass in a map of all the relevant
information. It might help to split up your calculator into multiple
functions, each of which deals with only part of the map. It might
even make sense to group the arguments a bit and pass in multiple
maps, or just some args outside of a map. The ideal is that a function
depends only on its parameters. Having many rebindable globals is
certainly *not* the way to go. :) For derived values, you might be
able to use let-bound locals.


 Now please look at a test I wrote to make sure the function does what
 I think it does:

 (deftest tax_deductible_expenses_basic
   (binding
     [*Months_To_Find_Tenant* 5
      *Months_In_Lease* 5
      *Lease_Cycles* 1
      *House_Sales_Price_0* 300
      *Monthly_Inflation_Rate* 0.002
      *Buying_Agent_Fee_Type* :Percentage
      *Buying_Agent_Fee_Number* 0.05
      *Selling_Agent_Fee_Type* :FlatFee
      *Selling_Agent_Fee_Number* 1000
      *Other_Sales_Fee_0* 100
      *Excise_Tax* 0.5
      *Original_Loan_Amount* 1
      *Monthly_Loan_Interest* (/ 0.05 12)
      *Months_In_Loan* (* 10 12)
      *Loan_Month_At_Start* 3
      *Prep_House_0* 100
      *Management_Fee* 2
      *Tenant_Finding_Fee* 0.5
      *Months_To_Sell* 3]
      (is (= (tax_deductible_expenses 0) (+ (fixed_monthly_cost 0)
 100)))
      (is (= (tax_deductible_expenses 1) (fixed_monthly_cost 1)))
      (is (= (tax_deductible_expenses 5) (+ (fixed_monthly_cost 5) (*
 (rental_income 5) 2.5
      (is (= (tax_deductible_expenses 7) (+ (fixed_monthly_cost 7) (*
 (rental_income 7) 2
      (is (= (tax_deductible_expenses 10) (+ (fixed_monthly_cost 10)
 (inflate 100 10
      (is (= (tax_deductible_expenses 12) (fixed_monthly_cost 12)))
      (is (= (tax_deductible_expenses 13) (house_sales_expenses 13)

 For the method tax_deductible_expenses to run it ends up requiring 19
 user defined values. That's a whole lot of arguments to pass into a
 function. Obviously I could wrap them up in a StructMap but then I get
 expressions like (+ 1 (args :B)) which doesn't seem much better than
 (+1 (B)).

 The issue I'm really trying to put my finger on is - these arguments
 really and truly are 'constants' within the context of the calculator.
 But they are constants whose values are not known as compile time but
 rather are known at run time. Does Clojure have a way to express a
 'late bound' constant or is the 'right' solution to pass around 19+
 arguments to functions or passing around StructMaps or making
 everything into thunks?


If you're passing 19 arguments to a function, it's most likely doing
too much. See if you can split up the logic somewhat.

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


Re: newbie question: Please help me stop creating constructors

2010-02-16 Thread CuppoJava
What do you think of the following style?

(defmacro in-environment [env  body]
  `(binding [*months-to-find-tenant* (:months-to-find-tenant env)
 *months-in-lease* (:months-in-lease env)
 *lease-cycles* (:lease-cycles env)
 etc...]
 ~...@body))

So env is a map that would contain the appropriate constants that
you need. Whenever you need them you can access them like this:

(in-environment env
  (tax-deductible-expenses 1))


That being said, I am not sure if that's the way I would do it. But I
haven't seen the rest of your program and it's possible that this is
perfectly justified.

  -Patrick

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


Re: newbie question: Please help me stop creating constructors

2010-02-16 Thread Richard Newman

For the method tax_deductible_expenses to run it ends up requiring 19



user defined values. That's a whole lot of arguments to pass into a
function. Obviously I could wrap them up in a StructMap but then I get
expressions like (+ 1 (args :B)) which doesn't seem much better than
(+1 (B)).


Pass them in as a map, and destructure at the start of the function:

  (defn tax-deductible-expenses [{:keys [management-fee
 tenant-finding-fee ...]}]
...)


The issue I'm really trying to put my finger on is - these arguments
really and truly are 'constants' within the context of the calculator.
But they are constants whose values are not known as compile time but
rather are known at run time.


That they're constant does not mean that you shouldn't pass them as  
arguments to your functions.


Most values obtained from users or config files are such run-time  
constants. Heck, many values in most programs are -- HTTP listener  
port, log file location, etc.


You still invoke your HTTP server with a :port argument.

Indeed, the more fixed values you have, the less likely it is that you  
should define a var for each. Maybe one var containing a map, but I'd  
still pass the map around rather than having each function implicitly  
refer to it. It makes testing easier.




Does Clojure have a way to express a
'late bound' constant or is the 'right' solution to pass around 19+
arguments to functions or passing around StructMaps or making
everything into thunks?


The reason you pass them around as arguments is so that the behavior  
of your functions is precisely determined *only* by its arguments --  
they are pure.


That means that you can memoize them, easily write tests for them,  
have them work correctly when part of a lazy sequence (which will  
often be evaluated outside the scope of your bindings), etc.


For example: how would you compare the tax-deductible-expenses of two  
clients? You'd need to invoke the function twice, with a huge nest of  
bindings around each call. Much better would be to store the  
appropriate values in two maps, then say


  ( (tax-deductible-expenses 0 john-data)
 (tax-deductible-expenses 0 bill-data))

-R


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


Re: newbie question: Please help me stop creating constructors

2010-02-16 Thread Yaron
I have posted a file (http://www.goland.org/sellorrent.pdf) which
explains the math behind the calculator. The file gives all the
algebra needed to implement the calculator. At the moment I'm just
taking the boneheaded approach and implementing all the logic in
Clojure as more or less a one to one mapping of the functions in the
PDF file.

Please, please, please, keep in mind that the linked article is a very
rough, rough draft. It is not ready for prime time. I am only sharing
it so that you can see what I'm trying to implement and hopefully
guide me to the right way to implement it.

It seems however that the consensus of the group based on what I've
said so far is to pass around state in a structmap. This is nice in
that it makes each function completely self contained (e.g. no
external references). It's unfortunate in that it now means that every
single function needs this extra argument and every variable access
either needs to use the :keys feature in the arguments or has to
directly refer to the keys in the map.

I really wish there was a way for me to just declare a context, define
a bunch of statics and then define all my methods inside of that
context. But it doesn't seem like this is the clojure way of handling
the problem. Where as many aspects of functional programming make a
ton of sense to me having to carry a map around everywhere doesn't
seem like an advantage. But I'm probably just missing something.

   Yaron


On Feb 16, 1:20 pm, Richard Newman holyg...@gmail.com wrote:
  For the method tax_deductible_expenses to run it ends up requiring 19
  user defined values. That's a whole lot of arguments to pass into a
  function. Obviously I could wrap them up in a StructMap but then I get
  expressions like (+ 1 (args :B)) which doesn't seem much better than
  (+1 (B)).

 Pass them in as a map, and destructure at the start of the function:

    (defn tax-deductible-expenses [{:keys [management-fee
                                           tenant-finding-fee ...]}]
      ...)

  The issue I'm really trying to put my finger on is - these arguments
  really and truly are 'constants' within the context of the calculator.
  But they are constants whose values are not known as compile time but
  rather are known at run time.

 That they're constant does not mean that you shouldn't pass them as  
 arguments to your functions.

 Most values obtained from users or config files are such run-time  
 constants. Heck, many values in most programs are -- HTTP listener  
 port, log file location, etc.

 You still invoke your HTTP server with a :port argument.

 Indeed, the more fixed values you have, the less likely it is that you  
 should define a var for each. Maybe one var containing a map, but I'd  
 still pass the map around rather than having each function implicitly  
 refer to it. It makes testing easier.

  Does Clojure have a way to express a
  'late bound' constant or is the 'right' solution to pass around 19+
  arguments to functions or passing around StructMaps or making
  everything into thunks?

 The reason you pass them around as arguments is so that the behavior  
 of your functions is precisely determined *only* by its arguments --  
 they are pure.

 That means that you can memoize them, easily write tests for them,  
 have them work correctly when part of a lazy sequence (which will  
 often be evaluated outside the scope of your bindings), etc.

 For example: how would you compare the tax-deductible-expenses of two  
 clients? You'd need to invoke the function twice, with a huge nest of  
 bindings around each call. Much better would be to store the  
 appropriate values in two maps, then say

    ( (tax-deductible-expenses 0 john-data)
       (tax-deductible-expenses 0 bill-data))

 -R

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


Re: newbie question: Please help me stop creating constructors

2010-02-16 Thread Richard Newman

It seems however that the consensus of the group based on what I've
said so far is to pass around state in a structmap.


Not necessarily a struct-map. Just a map.


This is nice in
that it makes each function completely self contained (e.g. no
external references). It's unfortunate in that it now means that every
single function needs this extra argument and every variable access
either needs to use the :keys feature in the arguments or has to
directly refer to the keys in the map.


Not necessarily. At some point your functions should be fine-grained  
enough that they only take a couple of arguments. As soon as you drop  
below 6 or 7, where they're all mandatory, switch to ordinary function  
argument style.


Wherever you call those functions should do the unpacking.

E.g.,

(defn outer-1 [{:keys [foo bar baz noo]}]
  (let [interm (foo-bar foo bar)
fiddle (frostrup baz noo)]
(tweep interm fiddle)))

After all, your house-sale-profit function should be expressed in  
terms of two arguments:


(defn house-sale-profit [house-sale-price house-sale-expenses]
  ...)

It doesn't care about the other 17.

Another thing: that big entry point function is like a much tidier  
version of the Java constructor that you created with 19 arguments --  
tidier in that you can use named keys or a map to identify the  
arguments.


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


Re: newbie question: Please help me stop creating constructors

2010-02-15 Thread Sean Devlin
Let's start with what you've got.  Could you post some of your code on
github, or something similar?  That would make it easier to help you
along.

Sean

On Feb 15, 12:24 pm, 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
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: newbie question: Please help me stop creating constructors

2010-02-15 Thread Richard Newman

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).



In Java, everything's an object, so you go about this by defining some  
class. All of its private members, its constructors, and its accessors  
are there to support one thing: should I sell or rent my home?


That is, rather than saying something like:

should-i-sell given that:
  current-home-price = 100,000
  current-interest-rate = 5.2%
  ...

you say

HomeCalculator c = new HomeCalculator(10, 5.2, ...);
boolean shouldSell = c.shouldSell();

and the logic is tied up in the shouldSell method definition.

When someone calls .setA(...), you have to recompute B, or you have to  
make sure that B is dynamically computed in .getB().



That's not how you do things in a functional programming language. You  
don't define global variables B and A. Define functions that  
compute things; thread them together; and then push your values in the  
top.


Start from the bottom up and the top down together; build a tree of  
functions that compute what you want. For example, you might think  
ah, I need to figure out my monthly payment on my mortgage. That's a  
function of the initial principal, the term, and the rate:


(defn monthly-payment [principal term-in-months interest-rate]
  ...)

Then you want to figure out how much more or less you'll pay, assuming  
a growth in rents of a certain percentage, over some number of months  
spent living in the house. Let's start by computing a sequence of  
rents, increasing over time:


(defn monthly-rent [starting-value monthly-increase]
  (lazy-seq
starting-value
(monthly-rent (* (+ 1 monthly-percentage-increase) starting- 
value) monthly-increase)))


then we want to weigh these against each other:

(defn rent-cost-over-time [starting-value monthly-increase months]
  (reduce + (take months (monthly-rent starting-value monthly- 
increase)))


(defn mortgage-cost-over-time [principal term-in-months interest-rate  
months]

  (...))


You get the idea: you're building a library of *pure* functions, each  
of which does one thing to some inputs, and might rely on the others.


Now you're ready to phrase your question as a function:


(defn should-i-sell
  [initial-mortgage-principal
   monthly-interest-rate
   months-already-paid-into-house
   ...]
  )

If you want to use keywords to denote named arguments, you can do that:

(defn should-i-sell
  [ args]
  (let [{:keys [initial-mortgage-principal ...]} (apply hash-map args)]
...)


No bindings. No global definitions. No redefinition. No state. User  
input comes in to your function and is passed through other functions.  
Eventually you get a value. If the user input changes, re-run the  
function. Dataflow programming is overkill for what you're doing.


You don't have primary values and dependent values: you have  
function inputs, and functions that compute values from inputs.


Hope that helps...

-R

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