I am new to F# and fiddling just around with it. What get's me is:
let rec fact n =
match n with
| dummy when n < 2 -> 1
| _ -> n * fact (n - 1)
开发者_JAVA技巧
let x = 6
printfn "%d! = %d" x (fact x)
Why does F# needs this dummy placeholder between pipe and when? Dummy is even the whole time undefined and the compiler seems in some way to need and ignore it at the same time like a needed ghost symbol.
Thanks in advance.
The symbol doesn't have to be a dummy and can appear in the when clause. For example, your function could be rewritten:
let rec fact = function
| n when n < 2 -> 1
| n -> n * fact (n - 1)
Here, because we're using an anonymous pattern match with function
rather than match ... with
, the identifier actually matters.
Frequently you'll use a more complicated pattern, like
match p with
| i,j when i < j -> true
| _ -> false
Because the pattern being matched against almost always matters even when there is a when
clause, there isn't a special form which allows a when
clause without any pattern.
Of course, if you really do want it to be a dummy, you can use the pattern _
so that you don't need to come up with a new identifier name:
let rec fact n =
match n with
| _ when n < 2 -> 1
| _ -> n * fact (n - 1)
As others already explained, the dummy
value in your example can be replaced by an ignore pattern (written as _
) to keep the code more succinct. The match
construct is the most powerful when you need to decompose some value and in that case, you need the ability to define new symbols inside the pattern matching.
However, in your example, you're not really decomposing the value, so I would prefer simple if ... then
expression instead of more complex match
:
let rec fact n =
if n < 2 then 1
else n * fact (n - 1)
I think this is a more readable way of writing your original function (and is as functional as the other version - match
is simply more suitable when working with more complex types than integers).
dummy
just means a value (or more accurately pattern) that can match the value between match
and with
.
It is not visible outside your function, only local to the first case.
As kvb said you're not forced to name it dummy
, it can be any valid F# identifier.
It's very powerful since it can be used for decomposing types like tuples or list:
match l with
| head::tail -> tail // returns tail
| _ -> [] // returns an empty list
精彩评论