当参数是列表时,惰性函数会立即传递参数吗?

Will lazy function pass through the argument at once when the argument is a list?

假设您有一个不可变的数字列表 xs = [1,2,3,4,5,6,7,8] 和一个函数 doubleMe,它将每个元素乘以 2,然后 returns 一个新列表。

当我们调用doubleMe(doubleMe(doubleMe(xs)))时,惰性函数将如何工作?

doubleMe([1,2,3,4,5,6,7,8]) -> doubleMe(doubleMe([1,2,3,4,5,6,7,8])) -> doubleMe(doubleMe(doubleMe([1,2,3,4,5,6,7,8])))

doubleMe(doubleMe(doubleMe(1))) -> doubleMe(doubleMe(doubleMe(2))) -> ... -> doubleMe(doubleMe(doubleMe(8)))

假设 doubleMe 是延迟实现的,它的计算如下:

doubleMe (doubleMe (1:2:3:[]))
= doubleMe (2 : doubleMe (2:3:[]))
= 4 : doubleMe (doubleMe (2:3:[]))
= 4 : doubleMe (4 : doubleMe (3:[]))
= 4 : 8 : doubleMe (doubleMe (3:[]))
= 4 : 8 : doubleMe (6 : doubleMe [])
= 4 : 8 : 12 : doubleMe (doubleMe [])
= 4 : 8 : 12 : doubleMe []
= 4 : 8 : 12 : []

使用三个嵌套调用而不是两个,计算是类似的。

本质上,评估策略会找到 最外层 doubleMe 调用,该调用具有弱头部范式的参数——即 [] 或形式 x : xs。然后它应用定义:

doubleMe [] => []
doubleMe (x:xs) => (2*x) : doubleMe xs