我开始阅读/研究clojure,为此我开始并行阅读“Programming Clojure”和“Practical Clojure”书籍。我看到了一个例子,说明懒惰的序列工作对我来说非常清楚,以便了解laq-seq是如何工作的,但遗憾的是它不起作用或者至少不是我期望的。
这是一个例子:
(defn square[x]
(do
(println "[current.elem=" x "]")
(* x x))
)
(def var-00 (map square '(1 2 3 5 6 4)))
我打电话的时候:
var-00
,我希望在控制台(REPL)上没有要打印的消息,但我得到了以下结果:
([current.elem= 1 ][current.elem= 2 ]1 [current.elem= 3 ]4 [current.elem= 5 ]9 [current.elem= 6 ]25 [current.elem= 4 ]36 16)
这意味着函数映射被调用,即使我期望没有任何事情发生,因为'var-00'只是对函数'map'的引用;如果我打电话的话,从我的观点来看更加尴尬:
(nth var-00 2)
我得到了:
[current.elem= 1 ][current.elem= 2 ][current.elem= 3 ]9
,如果我再次打电话:
(nth var-00 3)
我得到了:
[current.elem= 1 ][current.elem= 2 ][current.elem= 3 ][current.elem= 5 ]25;
之前的元素(1,2,3)再次计算我认为这些元素应该通过第一次调用“缓存”,现在只应计算元素5。我做错了什么或者我没有完全理解懒惰序列在clojure中是如何工作的?提到我使用IntellijIDEA和LaClojure插件来运行程序。
谢谢索林。
答案 0 :(得分:2)
刚刚在Clojure REPL检查了你的男女同校,这对我来说很好。每个元素只打印一次(第一次评估时)。
我甚至在Clojure online REPL中尝试了您的示例:
但有一件事你错了。 REPL执行每个命令然后打印其结果,因此当您键入var-00
REPL解析符号然后,为了打印它,执行整个惰性序列:
它与懒惰序列无关,它只是REPL的工作方式:
答案 1 :(得分:-3)
懒惰评估并不意味着事情会被缓存。这意味着在计算中,只有在结果需要时才会评估元素。如果结果需要两次元素,则可能会对其进行两次评估。
如果你想要自动缓存元素,那么就有memoize
函数,该函数将返回输入函数的转换版本,并添加了结果缓存。这也是实现动态编程的简便方法