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(100000, 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

Reply via email to