Thomas
Thomas

Reputation: 12107

Is that a proper use of match with in F# or is there a more idiomatic way to accomplish the same

The code is getting a json string from a server and parses it into a jObject and then branches appropriately.

                   let j = JObject.Parse x
                    match x, j with
                    | _ when x = "pong" -> ()
                    | _ when j.ContainsKey "table" -> HandleTableMessages j x
                    | _ when j.ContainsKey "success" -> HandleSuccessMessages j
                    | _ when j.ContainsKey "error" -> HandleErrorMessages j
                    | _ when j.ContainsKey "info" -> j.SelectToken "info"  |> string |> this.Print
                    | _, null -> this.Error ("malformed message: " + x)
                    | _ -> this.Error("unknown message type: " + x)

I think there is something a little bit heavy with the _ when part and I am wondering if there a better use of the F# grammar to express this?

Upvotes: 1

Views: 85

Answers (2)

Charles Roddie
Charles Roddie

Reputation: 947

It's a good sign that you realize this code is bad. It shows you may have better taste than most beginners. Using the simplest structure for a task is very important.

match x, j with
| _ when x = "pong" -> ()
...

First note that (x,j) is unused, so this simplifies to:

match () with
| _ when x = "pong" -> ()
...

Then you can realize that matching on a unit is silly, and that you should have used a simpler statement:

if x = "pong" then ()
elif j.ContainsKey "table" then HandleTableMessages j x
...
else this.Error("unknown message type: " + x)

I have just noticed that elif is not in the F# cheatsheet so I will try to get it added there as it's a basic keyword.

Upvotes: 4

Scott Hutchinson
Scott Hutchinson

Reputation: 1721

// Active Pattern
let (|Table|Success|Error|Info|Unknown|) (j: Newtonsoft.Json.Linq.JObject) =
    if j.ContainsKey "table" then Table
    elif j.ContainsKey "success" then Success
    elif j.ContainsKey "error" then Error
    elif j.ContainsKey "info" then Info
    else Unknown

match x, j with
| "pong", _ -> ()
| _, Table -> HandleTableMessages j x
| _, Success -> HandleSuccessMessages j
| _, Error -> HandleErrorMessages j
| _, Info -> j.SelectToken "info"  |> string |> this.Print
| _, null -> this.Error ("malformed message: " + x)
| _, Unknown
| _, _ -> this.Error("unknown message type: " + x)

Upvotes: 1

Related Questions