【问题标题】:How do variables in pattern matching allow parameter omission?模式匹配中的变量如何允许参数省略?
【发布时间】:2012-10-11 09:23:35
【问题描述】:

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

【问题讨论】:

  • 如果您将第二个代码 sn-p 中n 的第一次和第二次出现更改为另一个变量名,但将其他变量名保留为n,则该代码仍然有效。你明白为什么吗?
  • @sepp2k 是的,我知道我会使用一个变量来匹配 n 的材料。我不明白的是为什么第一个 sn-p 使用“函数”(据我所知,在这种情况下是“匹配 x 与”的语法糖)并且即使在我看来它也能工作,它会检查 x 的值,而不是函数定义所要求的 n 的值。

标签: functional-programming pattern-matching ocaml exponentiation


【解决方案1】:

您的版本在语法上是正确的,产生了很好的答案,但执行时间很长。 在您的代码中,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

【讨论】:

  • OP 没有询问lets。
  • 感谢您提供有关 let 的提示!现在我明白了,当使用“函数”时,我实际上是在声明函数在 let 子句中声明的最后一个参数之后再接收一个参数。我应该删除问题吗?
  • 不,保留这个问题,它可能对其他人有用:stackoverflow.com/faq
【解决方案2】:

关键字“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。不过这不是问题,因为两个同名变量具有相同的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    相关资源
    最近更新 更多