2016-10-04 66 views
7

我有,我已經打包成一個功能幾種語言表達:擺脫「厄運金字塔」的F#

open FsVerbalExpressions 
open FsVerbalExpressions.VerbalExpression 
open System.Text.RegularExpressions 
open System 

let createOrVerbExFromList (verbExList: VerbEx list) = 
    let orVerbEx = 
     verbExList 
     |> List.reduce (fun acc thing -> verbExOrVerbEx RegexOptions.IgnoreCase acc thing) //simpleVerbEx 

    orVerbEx 

let k12VerbEx =  
    let kTo12 = ["SCHOOL"; "DIST"; "SD"; "HS"; "BD OF ED"] 
    kTo12 
    |> List.map (fun word -> VerbEx(word)) 
    |> createOrVerbExFromList 

let twoYearCollegeVerbEx = 
    VerbEx("2 Year College") 

let universityVerbEx = 
    VerbEx("UNIV") 

let privateSchoolVerbEx = 
    VerbEx("ACAD") 

//Here there be dragons: 
let newInst (x: string) = 
    match (isMatch x k12VerbEx) with 
    | true -> "K - 12" 
    | _ -> match (isMatch x twoYearCollegeVerbEx) with 
      | true -> "2 Year College" 
      | _ -> match (isMatch x universityVerbEx) with 
        | true -> "University" 
        | _ -> match (isMatch x privateSchoolVerbEx) with 
          | true -> "Private/Charter School" 
          | _ -> "Other" 

我想重寫newInst功能,使得它不再是「我的問題是我怎樣才能擺脫厄運的金字塔?可以我擺脫它嗎?我懷疑它會是某種async工作流程或其他計算表達式,但這些都是新對我

回答

16

如果y OU僅匹配針對布爾值,然後if ... elif足以:

let newInst (x: string) = 
    if isMatch x k12VerbEx then 
     "K - 12" 
    elif isMatch x twoYearCollegeVerbEx then 
     "2 Year College" 
    elif isMatch x universityVerbEx then 
     "University" 
    elif isMatch x privateSchoolVerbEx then 
     "Private/Charter School" 
    else 
     "Other" 

更靈活的可能性將是創建一個有源圖案:

let (|IsMatch|_|) f x = 
    if isMatch x f then Some() else None 

let newInst (x: string) = 
    match x with 
    | IsMatch k12VerbEx -> "K - 12" 
    | IsMatch twoYearCollegeVerbEx -> "2 Year College" 
    | IsMatch universityVerbEx -> "University" 
    | IsMatch privateSchoolVerbEx -> "Private/Charter School" 
    | _ -> "Other" 
+0

這是一個很好的介紹活動模式。你能告訴我活動模式中附加'| _'的意義嗎? – Steven

+2

「| _」表示部分活動模式,這意味着它可能不匹配所有值(這就是爲什麼它返回一個選項)。 [見文檔](http://stackoverflow.com/documentation/f%23/962/active-patterns/23523/complete-and-partial-active-patterns#t=201610041942173049847)關於總和部分AP之間的差異。在你的情況下,你可能實際上想寫一個總的AP,但是它的實現本身會受到厄運的同一個金字塔的影響:) – Tarmil

3

當恰好存在的代碼相同的形式的連續的重複,我更喜歡使用一個數據驅動的方法來代替:

let verbExStrings = 
    [ 
     (k12VerbEx, "K - 12") 
     (twoYearCollegeVerbEx, "2 Year College") 
     (universityVerbEx, "University") 
     (privateSchoolVerbEx, "Private/Charter School") 
    ] 

let newInst x = 
    verbExStrings 
    |> List.tryPick (fun (verbEx, string) -> if isMatch x verbEx then Some string else None) 
    |> function Some x -> x | _ -> "Other" 

這種方法的一個優點是,原始數據(verbExStrings)可以來我在其他地方很方便,並且與您的代碼實現無關。