Reputation: 28770
I have this equation in java that I want to translate into clojure:
limit = (int)(n*(Math.log(n) + Math.log(Math.log(n)))) + 3;
I want to avoid it turning into a sea of nested parenthesis, what is the best way of making this readable in clojure?
Upvotes: 2
Views: 132
Reputation: 783
You can also use Graph, especially if your formulas will grow bigger and if the speed isn't that much of an issue:
(use 'plumbing.core)
(require '[plumbing.graph :as graph])
(def limit-graph
{:log (fnk [n] (Math/log n))
:loglog (fnk [log] (Math/log log))
:logsum (fnk [log loglog] (+ log loglog))
:limit (fnk [n logsum] (-> logsum (* n) int (+ 3)))})
(def calc-limit (graph/compile limit-graph))
(:limit (calc-limit {:n 5}))
Upvotes: 2
Reputation: 3014
I have to agree with the other answers that a let
with some descriptive names is a little more enlightening to read. But if you want to do it with just a threading macro, that is possible using ìterate
:
(defn calc-limit [n]
(->> n
(iterate #(Math/log %))
(drop 1) ;;The first value is just n, with no logarithms applied
(take 2) ;;Taking the 1st and 2nd iterations of Math/log on n
(reduce +)
(* n)
int
(+ 3)))
Upvotes: 2
Reputation: 6073
You mention the threading macro in your question's title, so I'll provide a variant primarily focused on exactly that, using let
to avoid calculating (Math/log n)
twice:
(let [x (Math/log n)]
(-> (Math/log x)
(+ x)
(* n)
(int)
(+ 3)))
Side Note: Using let
makes sense when
Upvotes: 1
Reputation: 1576
You can use let
form to break the formula to simpler parts:
(defn calc-limit [n]
(let [log (Math/log n)
loglog (Math/log log)
logsum (+ log loglog)]
(-> n (* logsum) int (+ 3))))
(calc-limit 256) ; => 1861
Upvotes: 2