当memoised函数的参数是序列
时,如何记忆工作?(defn foo
([x] (println "Hello First") (reduce + x))
([x y] (println "Hello Second") (reduce + (range x y))))
(def baz (memoize foo))
传递一个arg:
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"
答案 0 :(得分:3)
memoize
适用于序列,你只需要比较苹果和苹果。 memoize
在先前使用的哈希映射中查找参数,因此您最终会比较序列。比较长序列需要很长时间,无论它们是否为载体:
user> (def x (vec (range 1000000)))
;; => #'user/x
user> (def y (vec (range 1000000)))
;; => #'user/y
user> (time (= x y))
"Elapsed time: 64.351274 msecs"
;; => true
user> (time (baz x))
"Elapsed time: 67.42694 msecs"
;; => 499999500000
user> (time (baz x))
"Elapsed time: 73.231174 msecs"
;; => 499999500000
当您使用非常短的输入序列时,时间由您的函数内的reduce
支配。但是很长一段时间你看到的实际上是memoize
内的比较时间。
技术上memoize
在所有序列中以相同的方式工作。但“技术上”的工作并不意味着“有用”。正如您自己发现的那样,使用昂贵的比较语义输入是无用的(实际上甚至可能是有害的)。你的第二个签名解决了这个问题。