在fsharp中使用模式匹配和按位组合枚举标志避免“让mutable”干净利落

时间:2014-11-07 01:13:45

标签: enums f# pattern-matching mutable bitwise-or

考虑以下(可变)示例:

let getRegexFlax flags =
    let mutable res = RegexOptions.None
    for ch in flags do
        match ch with
        | 's' ->  res <- res ||| RegexOptions.Singleline
        | 'x' ->  res <- res ||| RegexOptions.IgnorePatternWhitespace
        | 'i' ->  res <- res ||| RegexOptions.IgnoreCase
        | 'm' ->  res <- res ||| RegexOptions.Multiline
        | _   ->  raise (Exception("invalid flag"))
    res

我用这个例子来举例说明我们经常遇到的情况。这个想法很简单:基于字符串(或任何复杂条件),您需要组合零个或多个枚举标记。

我认为,最简单的方法就是如上所述,具有可变性。如果你不使用mutable,我可以想到无数其他方法,但似乎没有一个非常干净:

  • 结合返回标志的递归函数(繁琐)
  • Don Lime建议
  • enum.Combine,每个数组条目中都有if条件或模式匹配(丑陋)
  • 一系列|||组合表达式,每个表达式都有一个条件(也很难看)

我确信有一种更简单,更直接的方式,最好是模式匹配,当然,没有可变性。这可能是一天的晚些时候,但我现在根本无法想到它,有人能告诉我光明吗?

2 个答案:

答案 0 :(得分:3)

我会做类似的事情:

let chartoflag ch= 
    match ch with
    | 's' ->   RegexOptions.Singleline
    | 'x' ->   RegexOptions.IgnorePatternWhitespace
    | 'i' ->  RegexOptions.IgnoreCase
    | 'm' ->  RegexOptions.Multiline
    | _   ->  raise (Exception("invalid flag"))

flags |> Seq.map chartoflag |> Seq.fold (|||) RegexOptions.None

答案 1 :(得分:1)

您可以使用Seq.fold函数(假设flags是字符集合)

let getRegexFlax1 flags =
    flags 
    |> Seq.fold (fun acc ch -> 
                    match ch with
                    | 's' ->  acc ||| RegexOptions.Singleline
                    | 'x' ->  acc ||| RegexOptions.IgnorePatternWhitespace
                    | 'i' ->  acc ||| RegexOptions.IgnoreCase
                    | 'm' ->  acc |||  RegexOptions.Multiline
                    | _   ->  failwith "invalid flag") RegexOptions.None
相关问题