哪个阶段在按名称调用和按值调用之间有所区别?
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 一个空列表。
大多数其他语言都使用按值调用。 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 一个空列表。