views:

185

answers:

3

Hi, 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)

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.

Bye, Bernd

+1  A: 

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
Stringer Bell
+10  A: 

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) 
kvb
You should add an active pattern example.
gradbot
@gradbot: Hm I think this is quite an advanced feature for a beginner!
Stringer Bell
@Stringer Bell: True, though it is an awesome feature.
gradbot
In addition to these cases, you may call a method inside the `match` statement, in which case you'll need a variable in the "dummy" position in order to get access to the result. `match foo.Caclulate() with x when x < 2 -> 1 | x -> x`
Joel Mueller
+7  A: 

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).

Tomas Petricek