我知道你写了“没有添加像活动模式这样的东西”,但我会发布一个使用它们的解决方案。它们是此类问题的完美匹配,并且它们是非常标准的 F# 功能,因此您确实没有理由要避免使用它们。在这里使用活动模式使代码绝对更具可读性。
(如果你是 F# 初学者,我能理解你为什么要从一个简单的解决方案开始 - 无论如何,这可能是你最终学习活动模式的一个很好的动机 :-),它们并不像看起来那么难第一眼)
如果字符串被格式化为 IP 地址(由四个用“.”分隔的子字符串组成),您可以定义一个匹配的活动模式:
let (|IPString|_|) (s:string) =
match s.Split('.') with
| [|a;b;c;d|] -> Some(a, b, c, d) // Returns 'Some' denoting a success
| _ -> None // The pattern failed (string was ill-formed)
match s with
| IPString(a, b, c, d) ->
// Matches if the active pattern 'IPString' succeeds and gives
// us the four parts of the IP address (as strings)
(parseOrParts a, parseOrParts b, parseOrParts c, parseOrParts d)
| _ -> failwith "wrong format"
这是允许您在字符串不正确时处理大小写的正确方法。您当然可以定义一个永不失败的版本(如果字符串格式错误,则返回例如 0.0.0.0):
// This active pattern always succeeds, so it doesn't include the "|_|" part
// in the name. In both branches we return a tuple of four values.
let (|IPString|) (s:string) =
match s.Split('.') with
| [|a;b;c;d|] -> (a, b, c, d)
| _ -> ("0", "0", "0", "0")
let (IPString(a, b, c, d)) = str
(parseOrParts a, parseOrParts b, parseOrParts c, parseOrParts d)
我想大多数人都会同意这更具可读性。当然,如果您只想为单一目的的脚本编写一些简单的东西,那么您可以忽略警告,但对于更大的东西,我更喜欢活动模式。