当参数是列表时惰性评估如何工作?
How does lazy evaluation works when the argument is a list?
根据我的理解,惰性评估是在将参数传递给函数之前不对其进行评估,而仅在实际使用其值时进行评估。
但是在 haskell 教程中,我看到了一个示例。
xs = [1,2,3,4,5,6,7,8]
doubleMe(doubleMe(doubleMe(xs)))
作者说命令式语言可能会遍历一次列表并制作副本,然后 return 它。然后它会再通过列表两次并 return 结果。
但是在惰性语言中,它会首先计算
doubleMe(doubleMe(doubleMe(1)))
这将返回一个doubleMe(1)
,即2
。然后是4
,最后是8
.
所以它只会在列表中传递一个,并且只有在您真正需要它时才会传递。
这让我很困惑。懒惰的语言为什么不把列表作为一个整体,而是拆分呢?我的意思是我们可以在使用列表或表达式之前忽略它。但是我们在使用的时候需要对整个东西进行评估,不是吗?
像 [1,2,3,4,5,6,7,8]
这样的列表只是语法糖:1:2:3:4:5:6:7:8:[]
.
在这种情况下,列表中的所有值都是数字常量,但我们可以定义另一个更小的列表,如下所示:
1:1+1:[]
所有Haskell列表都是链表,这意味着它们有一个头和一个尾。在上面的例子中,头部是1
,尾部是1+1:[]
.
如果您只想要列表的头部,则没有理由评估列表的其余部分:
(h:_) = 1:1+1:[]
这里的h
指的是1
。如果您只需要 h
,则没有理由评估列表的其余部分 (1+1:[]
)。
这就是延迟计算列表的方式。 1+1
仍然是 thunk(未计算的表达式),直到需要该值。
根据我的理解,惰性评估是在将参数传递给函数之前不对其进行评估,而仅在实际使用其值时进行评估。
但是在 haskell 教程中,我看到了一个示例。
xs = [1,2,3,4,5,6,7,8]
doubleMe(doubleMe(doubleMe(xs)))
作者说命令式语言可能会遍历一次列表并制作副本,然后 return 它。然后它会再通过列表两次并 return 结果。
但是在惰性语言中,它会首先计算
doubleMe(doubleMe(doubleMe(1)))
这将返回一个doubleMe(1)
,即2
。然后是4
,最后是8
.
所以它只会在列表中传递一个,并且只有在您真正需要它时才会传递。
这让我很困惑。懒惰的语言为什么不把列表作为一个整体,而是拆分呢?我的意思是我们可以在使用列表或表达式之前忽略它。但是我们在使用的时候需要对整个东西进行评估,不是吗?
像 [1,2,3,4,5,6,7,8]
这样的列表只是语法糖:1:2:3:4:5:6:7:8:[]
.
在这种情况下,列表中的所有值都是数字常量,但我们可以定义另一个更小的列表,如下所示:
1:1+1:[]
所有Haskell列表都是链表,这意味着它们有一个头和一个尾。在上面的例子中,头部是1
,尾部是1+1:[]
.
如果您只想要列表的头部,则没有理由评估列表的其余部分:
(h:_) = 1:1+1:[]
这里的h
指的是1
。如果您只需要 h
,则没有理由评估列表的其余部分 (1+1:[]
)。
这就是延迟计算列表的方式。 1+1
仍然是 thunk(未计算的表达式),直到需要该值。