lazy-seq的分步示例

Ced*_*tin 5 equals clojure lazy-evaluation

我很难理解懒惰工作以及缓存是如何工作的.

我认为一个lazy-seq在工作中的分步示例在这里可以提供帮助.例如,我读过以下问题:

Clojure懒惰序列使用

但它仍然不清楚.

我的问题是该调用将如何确定另一个调用是否与缓存调用"相等"以及它在缓存中保留多长时间?我试图(源lazy-seq),但显然它是在Java的土地,所以我在这里运气不好.

对于一个简单的lazy-seq,只取一个参数(比如说两个幂的列表),如果我用5然后8调用它怎么办?这两个值是否被缓存?

如果我要通过缓存我已经称为惰性函数的每个输入来破坏内存,那么创建和缓存无限列表以获得无限结构的重点是什么?

因为它表示它会在每次后续调用中缓存结果......使用's'.

1:参数结果为'1'缓存2:结果为参数为'2'缓存3:结果为参数为'3'缓存... 2 30:我数到2 30并且它很好因为我很懒所有,但现在内存中有一个2**30缓存,缓存所有后续调用的所有后续调用.

或者它只是缓存的最后一个调用?

如果我写一个以树为参数的懒函数怎么办?它运行平等吗?关于传递的论点,知道是否需要进行新的评估?

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

Art*_*ldt 8

延迟序列中的"缓存"不是可变缓存,会像在webapp中使用的那样过期,它是一个大小为1的缓存,并且列表中的每个单元格中都有一个缓存.'cache'要么包含一个值,要么包含计算值的代码,而不是两者.一旦它计算了它缓存值的值(在那个单元格/条目中),如果有人再次读取单元格,它会直接给它们值,而不是调用代码.

这是一个简化的虚构repl会话来说明这一点:

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
Run Code Online (Sandbox Code Playgroud)

在这个例子中,每个单元最初包含(这是一个简化来说明这一点)生成值的代码和生成列表其余部分的代码(如果这是列表的末尾则为nil).一旦该单元格被实现(使其变得不紧密),它就会用实际值替换它的内容,因此它现在包含生成序列其余部分的值和代码.当读取列表中的下一个单元时,它将首先通过代码进行生成(包含在单元中),然后新单元中的第n个代码将生成该单元的值.