2015-02-10 62 views
2

我在Java這個公式,我要翻譯成的Clojure:Clojure中使用線程宏方程

limit = (int)(n*(Math.log(n) + Math.log(Math.log(n)))) + 3; 

我想避免它變成嵌套括號的海洋,是什麼使最好的方式這在clojure可讀嗎?

回答

2

您可以使用let形式打破公式來簡單的部分:

(defn calc-limit [n] 
    (let [log (Math/log n) 
     loglog (Math/log log) 
     logsum (+ log loglog)] 
    (-> n (* logsum) int (+ 3)))) 

(calc-limit 256) ; => 1861 
+0

這可能是一個味道的問題,但我寧願把logsum放在第一位。從某種意義上說,原木是一種「被踩踏」的價值,而不是n。 – si14 2015-02-10 15:04:56

+0

@ si14在我看來,即使從「線程」,「n」或「logsum」的角度來看,它們也是等價的。如果'loglog'和'logsum'不會被首先引入,那麼我同意'( - > log Math/log(+ log)(* n)int(+ 3))'會更習慣。在上面的例子中,爲了清晰起見,創建了額外的綁定。此外,最終表現看起來接近原始中綴記號,有些人可能認爲這是一個加號。 – Jarlax 2015-02-10 15:16:48

1

你提到你的問題的標題線程宏,所以我將提供主要集中正是在一種變體,使用let到避免計算(Math/log n)兩次:

(let [x (Math/log n)] 
    (-> (Math/log x) 
     (+ x) 
     (* n) 
     (int) 
     (+ 3))) 

旁註:使用let有道理當

  • 你已經有被使用一次以上的值,
  • 要通過意味深長命名中間結果,以提高可理解性,或
  • 您想您的問題分裂成更小的部分,以提高可讀性。
2

我不得不同意其他答案,let與一些描述性的名稱是有點更具啓發性的閱讀。但是如果你想只是一個線程宏來做到這一點,這是可能的使用ì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))) 
2

您還可以使用Graph,特別是如果你的公式將變得更大,如果速度沒有那麼多的問題:

(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}))