我从F#开始,我无法理解构造值初始化的最佳方法是什么:
let x = TryCalculateX() // for example, searching in DB
if x = null then
// for example, we create it ourself and out it into DB
let x = TryAnotherCalcultaion()
someProcessing x // x is now initialized => Ok
someProcessing x // here I use old, not initialized x! => Fails
Run Code Online (Sandbox Code Playgroud)
你如何处理类似的情况?
UPD.我设计的最好的是:
let getX() =
let res = TryCalculateX()
if res = null then
let res = TryAnotherCalcultaion()
res
else
res
Run Code Online (Sandbox Code Playgroud)
这不是很酷,恕我直言
Upd 2. @ChaosPandion提出了很好的解决方案:
let x =
match TryCalculateX() with
| null -> TryAnotherCalculation()
| x -> x
someProcessing x
Run Code Online (Sandbox Code Playgroud)
但是如果添加一个额外的嵌套级别,这也变得不是很好:
let x =
match TryCalculateX() with
| null ->
match TryAnotherCalculation() with
| null -> OneMoreCalculation()
| y -> y
| x -> x
someProcessing x
Run Code Online (Sandbox Code Playgroud)
也许有一些更普遍的模式适用?
更新3.再次感谢@ChaosPandion,这是一个通用的解决方案:
// Different initialization strategies
let x() = printfn("x"); None
let y() = printfn("y"); None
let z() = printfn("z"); Some(1)
// Sequence of strategies
let a = seq {
yield x()
yield y()
yield z()
}
// Initializing function
let init what = Seq.find (fun el -> Option.isSome el) what
// Initializing
let b = init a
Run Code Online (Sandbox Code Playgroud)
F#交互式打印:
xyz ... val b:int option = 1
以下是一个很好的约定.它可以使用,null但我会建议返回一个'a option类型.
选项
let x =
match TryCalculateX() with
| Some x -> x
| None -> TryAnotherCalculation()
someProcessing x
Run Code Online (Sandbox Code Playgroud)
空值
let x =
match TryCalculateX() with
| null -> TryAnotherCalculation()
| x -> x
someProcessing x
Run Code Online (Sandbox Code Playgroud)
序列
假设你写了每次返回的尝试,option那么你可以编写一个优雅的尝试序列.
let x = seq {
yield firstTry ()
yield secondTry ()
yield thirdTry ()
yield sensibleDefault
} |> Seq.pick id
someProcessing x
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
131 次 |
| 最近记录: |