我正在做一些家庭作业,但是我已经呆了几个小时了。我敢肯定这真的很琐碎,但是在挖掘所有可用文档后,我仍然无法将头缠住。有人可以帮我吗?基本上,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。但是,这不是问题,因为两个具有相同名称的变量具有相同的值。