clojure对表达式使用线程宏
我想将java中的这个等式转换为clojure:clojure对表达式使用线程宏,clojure,Clojure,我想将java中的这个等式转换为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 logl
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
您在问题的标题中提到了threading宏,因此我将提供一个变量,主要关注于此,使用
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)))
您也可以使用,特别是如果您的公式将变大,并且速度不是太大的问题时:
(使用“管道.核心”)
(需要“[Pimming.graph:作为图形])
(def)极限图
{:log(fnk[n](数学/日志n))
:loglog(fnk[log](数学/日志))
:logsum(fnk[loglog](+loglog))
:限制(fnk[n logsum](>logsum(*n)int(+3)))
(def计算极限(图表/编译极限图表))
(:极限(计算极限{:n5}))
这可能是口味的问题,但我宁愿把logsum放在首位。从某种意义上说,logsum是一个“被踩”的值,而不是n.@si14在我看来,即使从“线程化”的角度来看,n
或logsum
它们也是等价的。如果不首先引入loglog
和logsum
,那么我同意(>log Math/log(+log)(*n)int(+3))
将更为惯用。在上面的示例中,创建附加绑定只是为了清晰起见。此外,最后的表达式接近原始的中缀表示法,有些人可以认为是一个加号。