Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将接受惰性序列作为输入的Clojure函数记忆化_Clojure - Fatal编程技术网

将接受惰性序列作为输入的Clojure函数记忆化

将接受惰性序列作为输入的Clojure函数记忆化,clojure,Clojure,当记忆函数的参数是序列时,如何进行记忆工作 (defn foo ([x] (println "Hello First") (reduce + x)) ([x y] (println "Hello Second") (reduce + (range x y)))) (def baz (memoize foo)) 传递一个参数: (一) (二) 通过2个参数: (一) (二) 当传递2个参数时,函数的第二次运行似乎是我所期望的 然而,使用向量似乎是可行的 (time (baz

当记忆函数的参数是序列时,如何进行记忆工作

(defn foo
    ([x] (println "Hello First") (reduce + x))
    ([x y] (println "Hello Second") (reduce + (range x y))))


(def baz (memoize foo))
传递一个参数:

(一)

(二)

通过2个参数:

(一)

(二)

当传递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"

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
对所有序列都有效。但是“从技术上”工作并不意味着“有用”。正如你自己所发现的那样,使用昂贵的比较语义输入是无用的(实际上甚至是有害的)。您的第二个签名解决了这个问题。

Hmm。如何处理这个问题是一件棘手的事情——您需要使用整个序列来确定身份,以便进行比较,但能够支持ISeq的优势之一是可能会导致懒惰。因此,我可以看到当前语义的论点——我们不希望为了潜在地启用缓存而增加调用的前期成本(以完全实现理论上可能是无限的序列)……在实现层,问题是当序列用作映射中的键时会发生什么。也就是说,序列是否以反映其内容的方式支持
.hashCode
(因此O(n)需要评估),以反映其身份的方式支持
,或者根本不支持?@CharlesDuffy-序列比较的任何实现(hash码等)只能优化不平等的情况。因此,矛盾的是,当
memoize
被设计为有用时——当你在地图中有相等的键时——你最终会得到O(n)比较时间,不管实现是什么。故事的寓意——
memoize
并非设计用于长序列作为参数。
(time (baz 1 1000000)) ;=> Hello Second "Elapsed time: 18.619768 msecs"
(time (baz 1 1000000)) ;=> "Elapsed time: 0.069684 msecs"
(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"
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