懒惰的语言

use*_*112 5 ocaml

我理解如果我有语句c = a AND b,如果a是假的那么编译器就不会打扰评估b,它会知道结果因为a已经是假的.

但是,如果我有一个递归调用的函数并且将递归调用与AND进行AND运算会怎么样呢.

So myfunc input1 input2 = and[myfunc(input1),myfunc(input2)]
Run Code Online (Sandbox Code Playgroud)

如果一个函数从上面的递归函数调用树中的任何一点返回false,那么递归函数会调用终止,而值false是否只会在原始调用点进行求值?

换句话说,它会使用上面的懒惰评估吗?

Ada*_*ner 8

是.实际上,一个实现and是递归的(并没有添加任何严格性):

and :: [Bool] -> Bool
and []     =  True
and (x:xs) =  x && and xs
Run Code Online (Sandbox Code Playgroud)

为了表明这是有效的,你可以传递一个无限的Falses 列表and,并看到它返回

Prelude> and (repeat False)
False
Run Code Online (Sandbox Code Playgroud)

但请注意,这不适用于无限的Trues 列表,因为它将永远寻找a False,但永远不会找到它.


Nic*_* Wu 6

简而言之,答案是肯定的,Haskell在递归函数中会很懒惰.

懒惰&&不是一个特例:它是其定义的结果:

(&&) :: Bool -> Bool -> Bool
True  && y = y
False && _ = False
Run Code Online (Sandbox Code Playgroud)

在这里,Haskell的懒惰意味着它可以匹配第一个参数&&,而第二个参数不需要被评估以了解结果.

对于递归函数,and我们有定义:

and :: [Bool] -> Bool
and []     = True
and (b:bs) = b && and bs
Run Code Online (Sandbox Code Playgroud)

这是一个递归定义,Haskell是在这些值懒惰bbs在非空列表,如果需要将只进行评估:在这种情况下,定义&&迫使我们来看看第一个元素b,如果是False,则其余的bs不必评估.

这里的教训是,懒惰是Haskell凭借其模式匹配提供的东西:当消耗足够的输入来匹配模式时,其余的可以保持不被评估直到需要它为止.