Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Pattern matching with an argument

This is probably simple but can someone explain why the following pattern matching is not sensible? It says other rules e.g. 1, 0, _ will never be matched.

let matchTest(n : int) = 
    let ran = new Random()
    let i = ran.Next(0, 2)
    match i with
    | n -> printfn "%i" n
    | 1 -> printfn "1"
    | 0 -> printfn "0"
    | _ -> printfn "impossible"

The same thing for this:

let matchTest(n : int) = 
    let ran = new Random()
    let i = ran.Next(0, 2)
    let m = n
    match i with
    | m -> printfn "%i" m
    | 1 -> printfn "1"
    | 0 -> printfn "0"
    | _ -> printfn "impossible"

So why can't it match n or m directly here?

like image 759
stt106 Avatar asked Dec 14 '22 09:12

stt106


1 Answers

The n in the first example is a place-holder symbol which gets populated if the match succeeds. It's the same as writing:

let matchTest(n : int) = 
    let ran = new Random()
    let i = ran.Next(0, 2)
    match i with
    | x -> printfn "%i" x
    | 1 -> printfn "1"
    | 0 -> printfn "0"
    | _ -> printfn "impossible"

The symbol x is populated with the value of i if the match succeeds, and is then available to use on the right hand side of ->. This match always succeeds, which explains why the rest of the match cases are unreachable.

In your case, it just so happens that you've named the match variable n, which is the same name as the input argument.

It's not the same value, though. Instead, what happens is that a new value, also called n is being created, and the previous n is no longer accessible.

This is a language feature called shadowing.

You can also see it outside of pattern matching:

let foo n =
    let n = 1
    n

Example usage:

> foo 42;;
val it : int = 1
> foo 1337;;
val it : int = 1

As you can see, the let-bound n shadows the input argument n.

The second example in the OP, where you match on n is a variation on the first, so the same explanation applies.

like image 133
Mark Seemann Avatar answered Dec 30 '22 14:12

Mark Seemann