这是我书中的代码片段,我不确定匹配是如何工作的,因为它似乎第一种情况与所有内容相匹配。以下是Ocaml向我发出的警告:
# let zero = 0;;
# let one = 1;;
# let rec fib i =
match i with
zero -> zero
| one -> one
| j -> fib (j - 2) + fib (j - 1);;
Characters 57-60:
Warning: this match case is unused.
Characters 74-75:
Warning: this match case is unused.
| one -> one
^^^
| j -> fib (j - 2) + fib (j - 1);;
^
val fib : int -> int = <fun>
# fib 1;;
- : int = 1
# fib 2002;;
- : int = 2002
答案 0 :(得分:9)
这是一个相当常见的混乱来源。从本质上讲,您希望将模式视为从常量(如0
和1
)以及模式绑定的标识符构建。
当标识符出现在模式中时,它会匹配任何内容,并将匹配的值绑定到标识符。模式中的标识符 not 是指与标识符关联的任何先前值。实际上,您的模式将始终与第一个案例匹配,并将zero
绑定到i
的值。
您可以想象您希望能够为常量值指定名称,然后使用名称而不是模式中的常量。然而,OCaml(像其他FP语言一样)不会那样工作。一个优点(在我看来)是它保持简单。
答案 1 :(得分:0)
我认为我要补充一点,如果你把代码改写成如下,它会正常工作:
# let zero = 0;;
# let one = 1;;
# let rec fib i =
match i with
0 -> zero
| 1 -> one
| j -> fib (j - 2) + fib (j - 1);;
基本问题(在另一个答案中已经很好地解释)是你可以创建与全局变量同名的新局部变量,并且使用匹配左侧的任何变量名称只创建一个新的局部变量该名称的变量,并用匹配的任何东西填充它。正如j
是一个新的局部变量,它包含匹配的内容,zero
也是如此。以前在较大范围内声明的事实被Ocaml忽略(这就是为什么你可以愉快地写出像
let x = 1;;
let x = 2 in let x = 3 in x;;
得到3的结果。