2014-11-07 58 views
1

结合枚举标志考虑以下(可变)例如:避免“让可变”干净与模式匹配和位在fsharp

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 

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

这样做的最简单的方法,我想,就像上面那样,可变。如果你没有使用可变的,我能想到的其它无数种方法,但似乎都不是很干净:

  • 递归函数结合的返回标志(繁琐)
  • enum.Combine为唐赛姆表明,与一个如果条件或模式匹配在每个阵列条目(难看)
  • 长范围的|||组合表达式,每个具有一个条件(也难看)

我确信有一种更简单,更直接方式,最好是模式匹配,当然,没有可变性。这可能是一天的最后时刻,但我现在根本想不起来,任何人都可以向我展示光明?

回答

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 
+0

当然(facepalm)'Seq.fold'就是我需要的! – Abel 2014-11-07 03:21:50

1

你可以使用Seq.fold功能(假设标志是字符的集合)

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 
+0

标志是在我的例子一个字符串,它是一家集的字符,所以这个与约翰基本相同的答案,但后来被颠倒过来的,也会起作用。问题是,这是最可读的;)。 – Abel 2014-11-07 03:23:21