更多功能的方式来做到这一点?

时间:2014-05-01 20:14:00

标签: clojure functional-programming clojurescript

我发表的This帖子讨论了汤姆森的悖论,并在Clojure中模拟它。 state函数在time = t时返回灯的状态。

(defn thomsons-lamp []
  (iterate (fn [[onoff dur]]
             [(not onoff) (/ dur 2)])
           [true 1])) 

(defn state [t]
  (let [t-vals (map second (thomsons-lamp))]
    (loop [i 1]
      (if (<= t (apply + (take i t-vals)))
        ((comp first last) (take i (thomsons-lamp)))
        (recur (inc i))))))

如何定义清除state函数(最好没有循环/重复)?

2 个答案:

答案 0 :(得分:3)

这里唯一的罪孽是

  • state
  • 中不必要的二次复杂度
  • 博文中浮点使用和错误的证据。编写的代码应该使用比率 - (状态2)不应该终止...

减少/减少将是您state功能的良好候选者。

(defn thomsons-lamp []
  (map vector (iterate not true) (iterate #(* 1/2 %) 1)))

(defn state [t]
  (reduce (fn [[s1 t1] [s2 t2]] 
            (if (>= t1 t) (reduced s1) [s2 (+ t1 t2)]))
          (thomsons-lamp)))

答案 1 :(得分:3)

Clojure中的单行解决方案

在Clojure中,虽然不是在ClojureScript中,但我们可以将state函数表示为一系列纯函数应用程序:

(defn state [t]
  (-> t rationalize / biginteger .bitLength odd?))

或者,不使用线程宏

(defn state [t]
  (odd? (.bitLength (biginteger (/ (rationalize t))))))

让我们测试一下:

(map (juxt identity state) [1 0.7 0.5 0.4 0.3 0.2])
; ([1 true] [0.7 true] [0.5 false] [0.4 false] [0.3 false] [0.2 true])

一步一步地采取行动:

(defn state [t]
  (-> t
      rationalize ; convert to a ratio to avoid losing precision using floating point
      /           ; take the reciprocal
      biginteger  ; round down (if need be) to a java.math.BigInteger 
      .bitLength  ; take its length in bits (a method, not a Clojure function)
      odd?        ; ask whether odd
      ))

它是如何运作的?

而不是测试给定数字t在一系列切换点

中的位置
1 1/2 1/4 1/8 ...

我们测试1/t(Clojure中的(/ t))在倒置切换点系列中的位置

1 2 4 8 ... 

,二进制,

1 10 100 1000 ... 

中最小的数字
1 2 3 4 ... 

二进制数字。

应用BigInteger/bitLength告诉我们有多少二进制数字1/t - 四舍五入无效。这是1 2 4 8 ...到达的系列1/t的术语数。所以答案是这个数字是否是奇数。