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

时间:2012-10-21 09:34:30

标签: functional-programming pattern-matching ocaml exponentiation

我正在做一些功课,但我已经被困了好几个小时了。 我确信它真的很微不足道,但在深入了解所有可用的文档后,我仍然无法绕过它。 有人可以帮我一把吗? 基本上,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
   ;;

我特别不明白的是如何从fun语句中省略参数n以及为什么它应该用作与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))
   ;;

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

关键字“function”不是

的语法糖
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。但这不是问题,因为具有相同名称的两个变量具有相同的值。