Избавляемся от "пирамиды гибели" в 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
рабочий процесс или другое вычислительное выражение, но все это очень ново для меня.
2 ответа
Если вы совпадаете только с логическими значениями, то 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"
Когда происходит последовательное повторение одного и того же вида кода, я предпочитаю использовать подход, основанный на данных:
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
) может пригодиться в других местах и не привязан к реализации вашего кода.