哪个阶段在按名称调用和按值调用之间有所区别?

Which stage make difference between call-by-name and call-by-value?

大多数其他语言都使用按值调用。 Haskell 使用按名称调用(懒惰评估),我想知道它是如何运行的,我认为它会比按值调用更好。

举个例子,
重复函数定义如下:

repeat' :: a -> [a]   
repeat' x = x:repeat' x

使用repeat' 3 将得到无限列表 3,
ghci> repeat' 3会生成3个连续的,
但是 take 5 (repeat' 3) 只会得到 [3,3,3,3,3].
haskell 如何知道以第五次递归内部 repeat' 函数结束?再说了,我觉得也不是take的问题。

代码执行到哪个阶段跟call-by-value有什么区别?

谢谢

你得到一个无限的 3 列表,因为在交互式会话中键入 repeat' 3 本质上调用 show (repeat' 3),而 show 试图遍历整个 return 值repeat' 3。另一方面,take 仅尝试从列表中获取有限数量的元素。这是 Prelude 中的定义:

take n _      | n <= 0 =  []
take _ []              =  []
take n (x:xs)          =  x : take (n-1) xs

比较repeat'repeat' x = x:repeat' x的定义和take匹配的模式。当您调用 take 5 (repeat' 3) 时,最后一个模式适用,因此它变为 take 5 (3:repeat' 3) = 3 : take 4 (repeat' 3)。由于惰性求值,repeat' 仅在任何给定步骤进行必要的求值,在本例中这意味着提取第一个元素以匹配模式 x:xs。因此,take 构建了一个 5 个 3 的列表,当 take 0 (repeat' 3) 匹配并且递归终止时终止,忽略对 repeat' 的未计算调用 return 一个空列表。