2014-11-07 61 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