问题描述
我构建了一个玩具电子表格来帮助学习 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))