我很难理解延迟工作以及缓存的工作方式。

我认为工作中的惰性序列的分步示例确实可以在这里有所帮助。例如,我已阅读以下问题:

Clojure lazy sequence usage

但是还不清楚。

我的问题是该调用如何确定另一个调用是否与缓存的调用“相等”,以及该调用在缓存中保留多长时间?我试图(获取lazy-seq的源代码),但是显然它在Java领域,所以我在这里很不走运。

对于一个简单的lazy-seq,仅接受一个参数(例如说2的幂的列表),如果我先用5再用8来称呼它,该怎么办?是否仅缓存了这两个值?

如果要通过缓存已经调用过惰性函数的每个输入来破坏内存,那么创建和缓存无限列表以获取无限结构又有什么意义呢?

因为它说它在以后的每次调用中都缓存结果...带有“s”。



还是只是缓存的最后一个电话?

如果我编写一个以树为参数的惰性函数怎么办?它等于运行吗?关于传递的论据,以了解是否需要进行新的评估?

可以在运行时以某种方式跟踪此行为吗?

最佳答案

延迟序列中的“缓存”不是可变的缓存,它不会像在Webapp中使用的那样使事物过期,它是大小为1的缓存,并且列表中的每个单元格中都有一个。该“缓存”要么包含一个值,要么包含用于计算该值的代码,并且永远不会同时包含这两个值。一旦计算出该值,它将缓存该值(在该单元格/条目中),如果有人再次读取该单元格,它将直接为他们提供该值,而不是调用代码。

这是一个简化的假想repl session 来说明这一点:

user> (def a (range))
a = [code-for-rest]
user> (first a)
a = [code-for-first, code-for-rest]
a = [0, code-for-rest]
result=> 0
user> (first a)
a = [0, code-for-rest]
result=> 0
user> (nth a 10)
a = [0]->[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]->[9, code-for-rest]
result=> 4

在此示例中,每个单元格最初包含(用于简化说明这一点),用于生成值的代码和用于生成列表的其余部分的代码(如果为列表的末尾,则为nil)。一旦实现了该单元格(使其变得懒惰),便用实际值替换其内容,因此它现在包含该值和生成其余序列的代码。当读取列表中的下一个单元格时,它将首先由静态代码(包含在该单元格中)生成(然后包含在该单元格中),然后新单元格中的第n个代码将生成该单元格的值。

10-06 05:14