如何在匹配中的保护表达式中使用 TryParse?

问题描述

我构建了一个玩具电子表格来帮助学习 F#。当我处理新单元格的文本时,我将其存储为可区分类型。要解析它,我觉得我应该能够执行以下操作:

        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)

我尝试了很多组合,但我无法在警卫中获得 TryParse。我写了一个帮手:

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

我现在可以写:

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

这似乎是一个糟糕的解决方案,因为它丢弃了转换后的结果。使 TryParse 进入警卫的正确语法是什么?

解决方法

我认为 active pattern 可以满足您的需求:

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)

但如果您真的希望 TryParse 处于守卫条件(并且您不介意解析两次),您可以这样做:

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