【发布时间】:2016-07-31 15:07:29
【问题描述】:
当 memoised 函数的参数是一个序列时,我如何让 memoize 工作
(defn foo
([x] (println "Hello First") (reduce + x))
([x y] (println "Hello Second") (reduce + (range x y))))
(def baz (memoize foo))
传递一个参数:
1)
(time (baz (range 1 1000000))) ;=> Hello First "Elapsed time: 14.870628 msecs"
2)
(time (baz (range 1 1000000))) ;=> "Elapsed time: 65.386561 msecs"
传递 2 个参数:
1)
(time (baz 1 1000000)) ;=> Hello Second "Elapsed time: 18.619768 msecs"
2)
(time (baz 1 1000000)) ;=> "Elapsed time: 0.069684 msecs"
传递 2 个参数时函数的第二次运行似乎是我所期望的。
但是使用矢量似乎可以工作...
(time (baz [1 2 3 5 3 5 7 4 6 7 4 45 6 7])) ;=> Hello First "Elapsed time: 0.294963 msecs"
(time (baz [1 2 3 5 3 5 7 4 6 7 4 45 6 7])) ;=> "Elapsed time: 0.068229 msecs"
【问题讨论】:
-
嗯。如何处理是一件棘手的事情——为了比较的目的,需要消耗整个序列来确定身份,但是能够支持 ISeq 的优势之一是潜在的懒惰。所以我可以看到当前语义的论点——我们不想增加调用的前期成本(为了完全实现理论上可能是无限的序列)以潜在地启用缓存。
-
...在实现层,问题是当序列用作映射中的键时会发生什么。 IE。序列是否以反映其内容的方式支持
.hashCode(因此需要评估O(n)),以反映其身份的方式(这样相同的序列只会与自身比较),还是根本不支持? -
@CharlesDuffy - 序列比较(哈希码等)的任何实现只能优化不等式的情况。所以自相矛盾的是,当
memoize被设计为有用时——当你在地图中有相等的键时——无论实现是什么,你最终都会得到 O(n) 比较时间。故事的寓意 -memoize并非设计用于将长序列用作参数。
标签: clojure