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