F# explicit match vs function syntax

2019-01-13 14:39发布

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 f#
8条回答
SAY GOODBYE
2楼-- · 2019-01-13 14:47

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.

查看更多
Explosion°爆炸
3楼-- · 2019-01-13 14:52

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 ??"
查看更多
做个烂人
4楼-- · 2019-01-13 14:54

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

查看更多
放我归山
5楼-- · 2019-01-13 14:55

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]
查看更多
做自己的国王
6楼-- · 2019-01-13 14:57

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"
查看更多
爱情/是我丢掉的垃圾
7楼-- · 2019-01-13 15:02

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.

查看更多
登录 后发表回答