dagda1
dagda1

Reputation: 28770

clojure use threading macro for equation

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

Answers (4)

si14
si14

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

Magos
Magos

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

xsc
xsc

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

  • you've values that have to be used more than once,
  • you want to improve understandability by expressively naming intermediate results, or
  • you want to improve readability by splitting up your problem into smaller parts.

Upvotes: 1

Jarlax
Jarlax

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

Related Questions