3

我是 F# 的新手,只是在摆弄它。我得到的是:

let rec fact n =
  match n with 
    | dummy when n < 2 -> 1
    | _ -> n * fact (n - 1)

let x = 6
printfn "%d! = %d" x (fact x)

为什么 F# 在管道和何时需要这个虚拟占位符?Dummy 甚至一直是未定义的,编译器似乎以某种方式需要并同时忽略它,就像需要的幽灵符号一样。

提前致谢。

4

3 回答 3

10

该符号不必是虚拟符号,可以出现在 when 子句中。例如,您的函数可以重写:

let rec fact = function
| n when n < 2 -> 1 
| n -> n * fact (n - 1) 

在这里,因为我们使用的是匿名模式匹配function而不是match ... with,所以标识符实际上很重要。

通常你会使用更复杂的模式,比如

match p with
| i,j when i < j -> true
| _ -> false

因为即使有when子句,匹配的模式几乎总是很重要,所以没有一种特殊的形式允许when没有任何模式的子句。

当然,如果你真的希望它是一个虚拟的,你可以使用这个模式_,这样你就不需要想出一个新的标识符名称:

let rec fact n = 
  match n with  
  | _ when n < 2 -> 1 
  | _ -> n * fact (n - 1) 
于 2010-08-29T17:33:38.553 回答
9

正如其他人已经解释的那样,dummy您的示例中的值可以替换为忽略模式(写为_),以使代码更简洁。match当您需要分解某些值时,该构造是最强大的,在这种情况下,您需要能够在模式匹配中定义新符号。

但是,在您的示例中,您并没有真正分解值,所以我更喜欢简单if ... then的表达式而不是更复杂的match

let rec fact n = 
  if n < 2 then 1 
  else n * fact (n - 1) 

我认为这是编写原始函数的一种更易读的方式(并且与其他版本一样实用——match在处理比整数更复杂的类型时更适合)。

于 2010-08-29T18:24:32.000 回答
1

dummy仅表示可以匹配 和 之间的值的值(或更准确地说是模式matchwith。它在您的函数之外不可见,仅在第一种情况下可见。

正如 kvb 所说,您不必为它命名dummy,它可以是任何有效的 F# 标识符。

它非常强大,因为它可以用于分解元组或列表等类型:

match l with
| head::tail -> tail // returns tail
| _ -> [] // returns an empty list
于 2010-08-29T17:28:31.510 回答