我在Java这个公式,我要翻译成的Clojure:Clojure中使用线程宏方程
limit = (int)(n*(Math.log(n) + Math.log(Math.log(n)))) + 3;
我想避免它变成嵌套括号的海洋,是什么使最好的方式这在clojure可读吗?
我在Java这个公式,我要翻译成的Clojure:Clojure中使用线程宏方程
limit = (int)(n*(Math.log(n) + Math.log(Math.log(n)))) + 3;
我想避免它变成嵌套括号的海洋,是什么使最好的方式这在clojure可读吗?
您可以使用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
你提到你的问题的标题线程宏,所以我将提供主要集中正是在一种变体,使用let
到避免计算(Math/log n)
两次:
(let [x (Math/log n)]
(-> (Math/log x)
(+ x)
(* n)
(int)
(+ 3)))
旁注:使用let
有道理当
我不得不同意其他答案,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)))
您还可以使用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}))
这可能是一个味道的问题,但我宁愿把logsum放在第一位。从某种意义上说,原木是一种“被踩踏”的价值,而不是n。 – si14 2015-02-10 15:04:56
@ si14在我看来,即使从“线程”,“n”或“logsum”的角度来看,它们也是等价的。如果'loglog'和'logsum'不会被首先引入,那么我同意'( - > log Math/log(+ log)(* n)int(+ 3))'会更习惯。在上面的例子中,为了清晰起见,创建了额外的绑定。此外,最终表现看起来接近原始中缀记号,有些人可能认为这是一个加号。 – Jarlax 2015-02-10 15:16:48