How can I use TryParse in a guard expression in match?

Viewed 50

I have built a toy spreadsheet to help learn F#. When I process the text for a new cell I store it as a discriminated type. To parse it I feel I should be able to do something like:

        let cv =
            match t with
            | _ when t.Length=0 -> Empty
            | x when t.[0]='=' -> Expr(x)
            | x when t.[0]='\"' -> Str(x)
            | (true,i) when Int32.TryParse t -> IntValue(i) // nope!
            | _ -> Str(t)

I have tried quite a few combinations but I cannot get TryParse in the guard. I have written a helper:

let isInt (s:string) = 
    let mutable m:Int64 = 0L
    let (b,m) = Int64.TryParse s
    b

I can now write:

|    _ when Utils.isInt t -> IntValue((int)t)  

This seems like a poor solution as it discards the converted result. What the correct syntax to get TryParse into the guard?

1 Answers

I think an active pattern will do what you want:

let (|Integer|_|) (str: string) =
   let flag, i = Int32.TryParse(str)
   if flag then Some i
   else None

let cv =
    match t with
    | _ when t.Length=0 -> Empty
    | x when t.[0]='=' -> Expr(x)
    | x when t.[0]='\"' -> Str(x)
    | Integer i -> IntValue(i)
    | _ -> Str(t)

But if you really want TryParse in the guard condition (and you don't mind parsing twice), you could do this:

| x when fst (Int32.TryParse(t)) -> IntValue (Int32.Parse(x))
Related