Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern matching multiple variables

I'm new to F# and haven't seen anywhere how to do the following correctly

let fun1 a b =
match a b with
| a + b > 0 -> fun2
| a + b < 0 -> fun3

I have to do this with pattern matching—for homework—but I don't know how to do it correctly. I thought I could be use tuples as follows:

let fun1 (a,b) =
match (a,b) with
| (a,b) when a + b > 0 -> fun2
| (a,b) when a + b < 0 -> fun3

But that doesn't work too. How do I proceed?

like image 765
Javier Lorenzini Avatar asked Mar 13 '14 13:03

Javier Lorenzini


2 Answers

You have the right idea, you just forgot that indentation matters in F#. Adding spaces makes you solution work:

let fun1 (a,b) =  
    match (a,b) with
    | (a,b) when a + b > 0 -> fun2
    | (a,b) when a + b < 0 -> fun3

This actually patterns matches twice, so we might want to rewrite it:

let fun1 t = function 
    | (a,b) when a + b > 0 -> fun2
    | (a,b) when a + b < 0 -> fun3

The compiler/interpreter will let this go through, but with a warning:

warning FS0025: Incomplete pattern matches on this expression.

I'll leave getting rid of that as an exercise :-)

PS. Good of you to be upfront about this being homework.

like image 118
Søren Debois Avatar answered Sep 27 '22 19:09

Søren Debois


Søren Debois is correct. Here are a few other notes:

  1. a and b are already in scope, so you don't need to match against them, you can match against anything:

    let fun1 (a,b) =
        match () with
        | () when a + b > 0 -> fun2
        | () when a + b < 0 -> fun3
    
  2. For that reason, an using an if statement might be more idiomatic.

  3. You're clearly missing the case when a + b = 0; note that the compiler always assumes that a when clause might not cover anything, so you'll still get a warning that some cases may be unhandled even if you add a | () when a + b = 0 -> ... case; you'd need to do just | () -> ... or | _ -> ... instead.

  4. There's a built-in shortcut for definitions of the form let f <pattern> = match <same pattern> with |..., which is let f = function |.... You'd use it like:

    let fun1 = function
    | (a,b) when a + b > 0 -> fun2
    | ...
    

    Note that now a and b aren't bound by the function definition, so the idea from my first note doesn't apply and you have to introduce them in the pattern.

like image 42
kvb Avatar answered Sep 27 '22 19:09

kvb