在闭包中使用瞬态

时间:2016-11-17 00:06:52

标签: clojure

我尝试重写memoize以便在单个线程上使用瞬态而不是原子来查看它在我的场景中是否更快但它仅适用于前8个调用。为什么?这是代码(Clojure 1.8):

(defn transient-memoize [f]
  (let [mem (transient {})]
    (fn [& args]
      (let [v (mem args ::none)]
        (if (= v ::none)
          (let [ret (apply f args)]
            (assoc! mem args ret)
            ret)
          v)))))

(defn slow-add [x y]
  (println "slow-add" x y)
  (Thread/sleep 10)
  (+ x y))

(defn call-add [memoizer]
  (let [f (memoizer slow-add)]
    (reduce +
            (for [i (range 10)
                  _ (range 2)]
              (f 100 i)))))

(call-add memoize)

slow-add 100 0
slow-add 100 1
slow-add 100 2
slow-add 100 3
slow-add 100 4
slow-add 100 5
slow-add 100 6
slow-add 100 7
slow-add 100 8
slow-add 100 9
=> 2090

(call-add transient-memoize)

slow-add 100 0
slow-add 100 1
slow-add 100 2
slow-add 100 3
slow-add 100 4
slow-add 100 5
slow-add 100 6
slow-add 100 7
slow-add 100 8
slow-add 100 8 ; <- called second time
slow-add 100 9
slow-add 100 9 ; <- called second time
=> 2090

更新

如果我初始化瞬态地图,它确实有效,因此它是TransientHashMap而不是TransientArrayMap。与普通地图不同,瞬态地图似乎不会随着集合的增长从ArrayMap自动转换为HashMap。总是这样吗?

(defn transient-memoize [f]
  (let [mem (transient (hash-map ::force-hash-map ::force-hash-map))]
    (fn [& args]
      (let [v (mem args ::none)]
        (if (= v ::none)
          (let [ret (apply f args)]
            (assoc! mem args ret)
            ret)
          v)))))

0 个答案:

没有答案