为什么用户没有定义条件工作?

wen*_*jay 0 ocaml

我目前正在研究OCAML,并且有一个关于用户定义的if-then的问题,例如:

let cond (c,t,e) =
   match c with
   | true -> t
   | false -> e
Run Code Online (Sandbox Code Playgroud)

在阶乘函数中使用时:

let rec fact n =
   cond (n=0,1, n * fact (n-1))
Run Code Online (Sandbox Code Playgroud)

直觉上,它似乎是正确的,但我知道它会抛出堆栈溢出错误.有人可以向我解释为什么会这样,以及这个用户定义的if-then如何与内置if-then不同?

Rad*_*dek 6

基本上你的用户定义的条件不是懒惰的评估.在实际匹配发生之前,OCaml会尝试评估您传递的两个表达式 - 对于truefalse案例.

例:

我们假设我们试图评估fact 2.

  • 返回值是表达式cond (2=0,1, 2 * fact (2-1)).在传递3元组之前cond,必须对其进行全面评估.要做到这一点,Ocaml必须评估该功能fact (2-1).

    • 现在我们评估fact 1.返回值是cond (1=0,1, 2 * fact (1-1)).同样,我们需要知道它的值fact (1-1),所以我们递归地计算它.
      • 我们评估fact 0.这里的问题开始显现.返回值是cond (0=0,1, 0 * fact (0-1)),但为了评估函数,cond我们首先要评估它的参数 - 3元组.这让我们评价fact (0-1)!
        • 然后,我们正在评估fact -1......
          • ...... fact -2...... fact -3堆栈溢出 s :)

内置的if-then懒惰地评估它的参数:首先,它检查条件是真还是假,然后它相应地只选择一个分支来评估 - 这种行为称为惰性评估.

实际上OCaml有操作lazy,force你可以用来避免这种不良行为,但可能只是坚持传统if.