Ocaml 为什么';这不是用户定义的条件工作吗?
我目前正在学习OCAML,对用户定义的if有疑问,例如: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有何不同吗?基本上,用户定义的
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
- 返回值是表达式
。在将3元组传递到cond(2=0,1,2*fact(2-1))
之前,必须对其进行完全评估。为此,Ocaml必须评估函数cond
fact(2-1)
- 现在我们评估
。返回值是cond(1=0,1,2*fact(1-1))。同样,我们需要知道事实1
的值,所以我们递归地计算它。事实(1-1)
- 我们评估
。这里开始出现问题。返回值是事实0
,但是为了计算函数cond(0=0,1,0*fact(0-1))
,我们首先必须计算它的参数-3元组。这使我们评估cond
!事实(0-1)
- 然后,我们评估
。。。事实-1
- <代码>事实-2<代码>事实-3。。。以及堆栈溢出s:)
- 然后,我们评估
- 我们评估
- 现在我们评估
实际上,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))
,我们首先必须计算它的参数-3元组。这使我们评估cond
!事实(0-1)
- 然后,我们评估
。。。事实-1
- <代码>事实-2<代码>事实-3。。。以及堆栈溢出s:)
- 然后,我们评估
实际上,OCaml有操作
lazy
和force
可以用来避免这种不受欢迎的行为,但是如果有人能告诉我为什么我的答案是-1,那么最好还是坚持传统的?我只是好奇,我相信它是正确的。我不知道为什么它被否决了,但我认为你是正确的。谢谢你的澄清。我也不明白,所以我投了你一票。至少如果有人投了反对票,他可以发表评论来解释原因。有人能告诉我为什么我的答案是-1吗?我只是好奇,我相信它是正确的。我不知道为什么它被否决了,但我认为你是正确的。谢谢你的澄清。我也不明白,所以我投了你一票。至少如果有人投了反对票,他可以发表评论来解释原因。作为补充说明,不要使用模式匹配来匹配值。更多信息。@RichouHunter,您反对变量上的模式匹配(如果编写者不理解他正在创建一个新的绑定…即使语言中的所有其他变量绑定构造的行为都是相同的)true
和false
虽然是值。与他们匹配没有什么令人困惑的。这与匹配[]
或Leaf
或任何其他变量构造函数完全相同。我认为如果不使用任何绑定,这是没有意义的,但我明白你的意思。作为补充,不要使用模式匹配来匹配值。更多信息。@RichouHunter,您反对变量上的模式匹配(如果编写者不理解他正在创建一个新的绑定…即使语言中的所有其他变量绑定构造的行为都是相同的)true
和false
虽然是值。与他们匹配没有什么令人困惑的。这与匹配[]
或Leaf
或任何其他变量构造函数完全相同。我认为如果不使用任何绑定,这是没有意义的,但我明白你的意思。