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