模式匹配中的变量如何允许参数省略



我正在做一些家庭作业,但是我已经呆了几个小时了。我敢肯定这真的很琐碎,但是在挖掘所有可用文档后,我仍然无法将头缠住。有人可以帮我吗?基本上,OCAML编程中的练习要求通过平方算法来定义功能x^n。

我已经看了解决方案:

   let rec exp x = function
    0 -> 1
   | n when n mod 2 = 0  -> let y = exp x (n/2) in y*y
   | n when n mod 2 <> 0 -> let y = exp x ((n-1)/2) in y*y*x
   ;;

我不明白的是如何从娱乐语句中省略参数n,以及为什么应该将其用作与x匹配的变量,而x与x的定义没有明显的链接。

这就是我的方式:

   let rec exp x n = match n with
   0 -> 1
   | n when (n mod 2) = 1 -> (exp x ((n-1)/2)) * (exp x ((n-1)/2)) * x
   | n when (n mod 2) = 0 -> (exp x (n/2)) * (exp x (n/2))
   ;;

您的版本在语法上是正确的,可以得出一个很好的答案,但可以执行。在您的代码中,exp被递归两次,因此得出的计算是两倍,每个调用的计算量是n=0的两倍。在解决方案中,exp仅称为一次,结果被存储在变量y中,然后将y平方。

现在,关于语法,

let f n = match n with
  | 0 -> 0
  | foo -> foo-1

等效于:

let f = function
  | 0 -> 0
  | foo -> foo-1

let rec exp x = function是乞讨两个参数: x的函数,也是模式匹配中使用的未征用参数。在模式匹配中,线

 | n when n mod 2 = 0  ->

命名此参数n。并不是说在图案匹配的每种情况下都可以使用其他名称(即使这还不太清楚):

| n when n mod 2 = 0  -> let y = exp x (n/2) in y*y
| p when p mod 2 <> 0 -> let y = exp x ((p-1)/2) in y*y*x

关键字"函数"不是

的语法糖
match x with

但是

fun x -> match x with

因此

let rec exp x = function

可以用

代替
let rec exp x = fun y -> match y with

当然等于您的解决方案

let rec exp x y = match y with

请注意,我写了" y",而不是" n",以避免混淆。比赛后引入的N变量是一个新变量,它仅与函数参数相关,因为它匹配它。例如,而不是

let y = x in ...

您可以写:

match x with y -> ...

在此匹配表达式中," y"表达式是与"模式"匹配的。像任何模式一样,它将其变量(此处y)绑定到匹配的值。(在这里,x的值)和任何模式一样,模式中的变量是新变量,可能会阴影先前定义的变量。在您的代码中:

let rec exp x n = match n with
  0 -> 1
  | n when (n mod 2) = 1 -> (exp x ((n-1)/2)) * (exp x ((n-1)/2)) * x
  | n when (n mod 2) = 0 -> (exp x (n/2)) * (exp x (n/2))
;;

在两种情况下,变量n阴影n。但是,这不是问题,因为两个具有相同名称的变量具有相同的值。

最新更新