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

时间:2017-12-19 01:30:41

标签: ocaml

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

let cond (c,t,e) =
   match c with
   | true -> t
   | false -> e

在阶乘函数中使用时:

let rec fact n =
   cond (n=0,1, n * fact (n-1))

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

1 个答案:

答案 0 :(得分: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有一些操作lazyforce可以用来避免这种不良行为,但最好只是坚持传统的if

相关问题