Haskell 按名称调用和按值调用的区别在哪个阶段?
大多数其他语言使用按值调用。Haskell使用按名称调用(惰性评估),我想知道它是如何运行的,我认为它比按值调用更好 以问题为例,Haskell 按名称调用和按值调用的区别在哪个阶段?,haskell,lazy-evaluation,Haskell,Lazy Evaluation,大多数其他语言使用按值调用。Haskell使用按名称调用(惰性评估),我想知道它是如何运行的,我认为它比按值调用更好 以问题为例, “重复”功能定义如下: repeat' :: a -> [a] repeat' x = x:repeat' x 使用repeat'3将获得一个无限的3个列表, ghci>重复'3将生成3个连续, 但是take 5(重复'3)只会得到[3,3,3,3] haskell如何知道以第五个递归内部repeat'函数结束?此外,我不认为这是采取行动的问题 当代码
“重复”功能定义如下:
repeat' :: a -> [a]
repeat' x = x:repeat' x
使用repeat'3
将获得一个无限的3个列表,ghci>重复'3
将生成3个连续,但是
take 5(重复'3)
只会得到[3,3,3,3]
haskell如何知道以第五个递归内部
repeat'
函数结束?此外,我不认为这是采取行动的问题
当代码执行到哪个阶段时,它与按值调用不同
谢谢您将得到一个无限的3个列表,因为在交互式会话中键入
repeat'3
实际上调用了show(repeat'3)
,并且show
尝试迭代repeat'3
的整个返回值<另一方面,code>take,只尝试从列表中获取有限数量的元素。以下是前奏曲中的定义:
take n _ | n <= 0 = []
take _ [] = []
take n (x:xs) = x : take (n-1) xs
取n | n简言之,总是减少最外层的表达式,它是可减少的:头(重复3)
->头(3:重复3)
->3
。在第一种情况下,head
是不可归约的,因为它必须在其参数上进行模式匹配,但其参数不是构造函数。但是,repeat
不进行模式匹配,因此可以减少模式匹配。在第一次缩减之后,head
现在可以缩减,因为有一个构造函数(the:
)“当代码执行到哪个阶段时,它与按值调用不同?”呃。。。什么?你会问这样的问题吗:假设我们使用按值调用作为传递函数参数的策略,而不是按名称调用,这会有什么不同吗?我相信,按价值调用,你实际上意味着急切的减少,在这种情况下,代码>重复3 只是“代码>未定义的< /代码>,所以<代码>取5未定义的/未定义的< /代码>,程序将永远被卡住。”Bakuriu,你可以把名字叫做懒惰的评价(这将是更好的理解)。。当表达式可以进行求值时,将使用按值调用,当然,只要编译器可以,Haskell不使用按值调用。我不明白你说的repeat 3只是未定义的,它将在哪一点进行计算。大多数其他语言(如c/c++)都使用按值调用,我想知道Haskell如何处理未定义的(repeat 3)?谢谢你的意思是说take
在开始时将3视为空列表吗?但是当take
尝试访问repeat 3
时,表达式不会被计算?它从不将(repeat'3)
视为空列表;相反,它在任何时间点都不会看头部以外的任何东西。未计算的尾部被传递给递归调用。此外,未计算的尾部在哪个点进行计算?