我会写一个orElse
函数。然后你可以这样做:
let orElse f = function
| None -> f()
| Some _ as x -> x
let getIndex connDB strTable =
getIndexByPrimaryKey connDB strTable
|> orElse (fun () -> getIndexByCluster connDB strTable)
|> orElse (fun () -> getIndexByFirstColumns connDB strTable)
|> orElse (fun () -> getIndexByOnlyUnique connDB strTable)
|> orElse (fun () -> getAnyUniqueIndex connDB strTable)
或者,如果您更喜欢“工作流”语法(并且经常需要这个),那么:
module OrElse =
let bind f = function
| None -> f()
| Some x -> Some x
let combine m1 m2 =
m1 |> bind (fun () -> m2)
type OrElseBuilder() =
member x.Zero() = None
member x.Return(v) = Some v
member x.Bind(m, f) = bind f m
member x.ReturnFrom(m) = m
member x.Combine(m1, m2) = combine m1 m2
member x.Delay(f) = f()
let orElse = OrElseBuilder()
会让你更简洁地陈述它:
open OrElse
orElse {
return! getIndexByPrimaryKey connDB strTable
return! getIndexByCluster connDB strTable
return! getIndexByFirstColumns connDB strTable
return! getIndexByOnlyUnique connDB strTable
return! getAnyUniqueIndex connDB strTable
}
由于您将相同的参数传递给每个函数,因此 pad 的解决方案可能尽可能简洁。这些解决方案解决了替换嵌套的一般问题match x with Some _ as v -> v | None -> ...
。
编辑
扩展 Tomas 的想法,您可以将通用的活动模式用于“模式化”功能:
let (|FN|_|) f x = f x
然后做:
match connDB, strTable with
| FN getIndexByPrimaryKey name -> Some name
| FN getIndexByCluster name -> Some name
| FN getIndexByFirstColumns name -> Some name
| FN getIndexByOnlyUnique name -> Some name
| args -> getAnyUniqueIndex args
这需要对您的函数稍作改动:args 必须是元组形式。