関数を書き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
}
すべての関数に同じ引数を渡しているため、パッドのソリューションは可能な限り簡潔になる可能性があります。これらのソリューションは、入れ子になった を置き換える一般的な問題に対処します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
これには、関数を少し変更する必要があります。引数はタプル形式でなければなりません。