tags:

views:

319

answers:

6

Sorry about the vague title, but part of this question is what these two syntax styles are called:

let foo1 x = 
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one"

The other part is what difference there is between the two, and when I would want to use one or the other?

+5  A: 

They do the same thing in your case -- the function keyword acts like a combination of the fun keyword (to produce an anonymous lambda) followed by the match keyword.

So technically these two are the same, with the addition of a fun:

let foo1 = fun x ->
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"
Tim Robinson
Isn't it actually the other way around - i.e. `fun` is technically defined in terms of `function | _ -> ...`?
Pavel Minaev
To be specific, `fun x y -> ...` would be `fun x -> fun y -> ...`, and then `fun x -> ...` would be `function | x -> ...`. It's why you can do pattern matching in `fun` - e.g. `fun (x::xs) -> ...`.
Pavel Minaev
+1  A: 

The two syntaxes are equivalent. Most programmers choose one or the other and then use it consistently.

The first syntax remains more readable when the function accepts several arguments before starting to work.

Pascal Cuoq
+9  A: 

The pro for the second syntax is that when used in a lambda, it could be a bit more terse and readable.

List.map (fun x -> match x with | 1 -> "one" | _ -> "not one") [0;1;2;3;1]

vs

List.map (function 1 -> "one" | _ -> "not one") [0;1;2;3;1]
Stringer Bell
+2  A: 

The match version is called a "pattern matching expression". The function version is called a "pattern matching function". Found in section 6.6.4 of the spec.

Using one over the other is a matter of style. I prefer only using the function version when I need to define a function that is only a match statement.

gradbot
+2  A: 

The function version is a short hand for the full match syntax in the special case where the match statement is the entire function and the function only has a single argument (tuples count as one). If you want to have two arguments then you need to use the full match syntax*. You can see this in the types of the following two functions.

//val match_test : string -> string -> string
let match_test x y = match x, y with
                        | "A", _ -> "Hello A"
                        | _, "B" -> "Hello B"
                        | _ -> "Hello ??"

//val function_test : string * string -> string                   
let function_test = function
                        | "A", _ -> "Hello A"
                        | _, "B" -> "Hello B"
                        | _ -> "Hello ??"

As you can see match version takes two separate arguments whereas the function version takes a single tupled argument. I use the function version for most single argument functions since I find the function syntax looks cleaner.

*If you really wanted to you can get the function version to have the right type signature but it looks pretty ugly in my opinion - see example below.

//val function_match_equivalent : string -> string -> string
let function_match_equivalent x y = (x, y) |> function
                                                | "A", _ -> "Hello A"
                                                | _, "B" -> "Hello B"
                                                | _ -> "Hello ??"
Joshua
+4  A: 

Just for completeness sake, I just got to page 321 of Expert FSharp:

"Note, Listing 12-2 uses the expression form function pattern-rules -> expression. This is equivalent to (fun x -> match x with pattern-rules -> expression) and is especially convenient as a way to define functions working directly over discriminated unions."

Benjol