Ocaml 为什么';这不是用户定义的条件工作吗?

Ocaml 为什么';这不是用户定义的条件工作吗?,ocaml,Ocaml,我目前正在学习OCAML,对用户定义的if有疑问,例如: 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有何不同吗?基本上,用户定义的

我目前正在学习OCAML,对用户定义的if有疑问,例如:

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有何不同吗?

基本上,用户定义的条件没有被计算。在实际匹配发生之前,OCaml会尝试对您传递的两个表达式求值,即
true
false
情况

例如:

假设我们尝试评估
事实2

  • 返回值是表达式
    cond(2=0,1,2*fact(2-1))
    。在将3元组传递到
    cond
    之前,必须对其进行完全评估。为此,Ocaml必须评估函数
    fact(2-1)

    • 现在我们评估
      事实1
      。返回值是cond(1=0,1,2*fact(1-1))。同样,我们需要知道
      事实(1-1)
      的值,所以我们递归地计算它。
      • 我们评估
        事实0
        。这里开始出现问题。返回值是
        cond(0=0,1,0*fact(0-1))
        ,但是为了计算函数
        cond
        ,我们首先必须计算它的参数-3元组。这使我们评估
        事实(0-1)
        • 然后,我们评估
          事实-1
          。。。
          • <代码>事实-2<代码>事实-3。。。以及堆栈溢出s:)
内置的if然后惰性地计算其参数:首先,它检查条件是否为true或false,然后它相应地只选择一个分支进行计算——这种行为称为惰性计算


实际上,OCaml有一些操作
lazy
force
,您可以使用它们来避免这种不良行为,但如果基本上用户定义的条件不是lazy,那么最好还是坚持使用传统的
。在实际匹配发生之前,OCaml会尝试对您传递的两个表达式求值,即
true
false
情况

例如:

假设我们尝试评估
事实2

  • 返回值是表达式
    cond(2=0,1,2*fact(2-1))
    。在将3元组传递到
    cond
    之前,必须对其进行完全评估。为此,Ocaml必须评估函数
    fact(2-1)

    • 现在我们评估
      事实1
      。返回值是cond(1=0,1,2*fact(1-1))
。同样,我们需要知道
事实(1-1)
的值,所以我们递归地计算它。
  • 我们评估
    事实0
    。这里开始出现问题。返回值是
    cond(0=0,1,0*fact(0-1))
    ,但是为了计算函数
    cond
    ,我们首先必须计算它的参数-3元组。这使我们评估
    事实(0-1)
    • 然后,我们评估
      事实-1
      。。。
      • <代码>事实-2<代码>事实-3。。。以及堆栈溢出s:)
内置的if然后惰性地计算其参数:首先,它检查条件是否为true或false,然后它相应地只选择一个分支进行计算——这种行为称为惰性计算


实际上,OCaml有操作
lazy
force
可以用来避免这种不受欢迎的行为,但是如果

有人能告诉我为什么我的答案是-1,那么最好还是坚持传统的
?我只是好奇,我相信它是正确的。我不知道为什么它被否决了,但我认为你是正确的。谢谢你的澄清。我也不明白,所以我投了你一票。至少如果有人投了反对票,他可以发表评论来解释原因。有人能告诉我为什么我的答案是-1吗?我只是好奇,我相信它是正确的。我不知道为什么它被否决了,但我认为你是正确的。谢谢你的澄清。我也不明白,所以我投了你一票。至少如果有人投了反对票,他可以发表评论来解释原因。作为补充说明,不要使用模式匹配来匹配值。更多信息。@RichouHunter,您反对变量上的模式匹配(如果编写者不理解他正在创建一个新的绑定…即使语言中的所有其他变量绑定构造的行为都是相同的)
true
false
虽然是值。与他们匹配没有什么令人困惑的。这与匹配
[]
Leaf
或任何其他变量构造函数完全相同。我认为如果不使用任何绑定,这是没有意义的,但我明白你的意思。作为补充,不要使用模式匹配来匹配值。更多信息。@RichouHunter,您反对变量上的模式匹配(如果编写者不理解他正在创建一个新的绑定…即使语言中的所有其他变量绑定构造的行为都是相同的)
true
false
虽然是值。与他们匹配没有什么令人困惑的。这与匹配
[]
Leaf
或任何其他变量构造函数完全相同。我认为如果不使用任何绑定,这是没有意义的,但我明白你的意思。