F# explicit match vs function syntax

SyntaxF#

Syntax Problem Overview


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?

Syntax Solutions


Solution 1 - Syntax

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]

Solution 2 - Syntax

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.

Solution 3 - Syntax

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 ??"

Solution 4 - Syntax

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"

Solution 5 - Syntax

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

Solution 6 - Syntax

function only allows for one argument but allows for pattern matching, while fun is the more general and flexible way to define a function. Take a look here: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html

Solution 7 - Syntax

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.

Solution 8 - Syntax

This is an old question but I will throw my $0.02.

In general I like better the match version since I come from the Python world where "explicit is better than implicit."

Of course if type information on the parameter is needed the function version cannot be used.

OTOH I like the argument made by Stringer so I will start to use function in simple lambdas.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBenjolView Question on Stackoverflow
Solution 1 - SyntaxStringerView Answer on Stackoverflow
Solution 2 - SyntaxgradbotView Answer on Stackoverflow
Solution 3 - SyntaxJoshuaView Answer on Stackoverflow
Solution 4 - SyntaxTim RobinsonView Answer on Stackoverflow
Solution 5 - SyntaxBenjolView Answer on Stackoverflow
Solution 6 - SyntaxkamaciView Answer on Stackoverflow
Solution 7 - SyntaxPascal CuoqView Answer on Stackoverflow
Solution 8 - SyntaxSoldalmaView Answer on Stackoverflow