F# 结构值初始化
我从F#开始,我不明白构造值初始化的最佳方法是什么:F# 结构值初始化,f#,F#,我从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
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
你如何处理类似的情况
Upd。我设计的最佳方案是:
let getX() =
let res = TryCalculateX()
if res = null then
let res = TryAnotherCalcultaion()
res
else
res
这可不太酷,伊姆霍
UPD2@ChaosPandion建议了一个很好的解决方案:
let x =
match TryCalculateX() with
| null -> TryAnotherCalculation()
| x -> x
someProcessing x
但如果增加一个额外的嵌套级别,这也不是很好:
let x =
match TryCalculateX() with
| null ->
match TryAnotherCalculation() with
| null -> OneMoreCalculation()
| y -> y
| x -> x
someProcessing x
也许有一些更普遍的模式可以应用
Upd 3。再次感谢@chaospanion,这里有一个通用的解决方案:
// 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
F#交互式打印:
x y z。。。val b:int选项=大约1
下面是一个很好的惯例。它可以使用
null
,但我建议返回一个'a选项
类型
选项
let x =
match TryCalculateX() with
| Some x -> x
| None -> TryAnotherCalculation()
someProcessing x
Null
let x =
match TryCalculateX() with
| null -> TryAnotherCalculation()
| x -> x
someProcessing x
序列
假设每次尝试都返回一个选项
,那么就可以编写一个优雅的尝试序列
let x = seq {
yield firstTry ()
yield secondTry ()
yield thirdTry ()
yield sensibleDefault
} |> Seq.pick id
someProcessing x
谢谢你的回复!你的代码看起来比我的原始版本更干净。同时,如果有更多的条件需要检查,例如,如果有三个而不是两个情况,甚至会变得混乱。你认为如何简化模式复杂情况?@Rustam-F#执行复杂模式匹配的能力应该涵盖很多情况。也就是说,您可以使用
when
保护来扩展它。有了这两种工具,您应该能够编写富有表现力且简洁的代码。我会通读文档以真正理解它。@Rustam-我几乎忘了提到哪一个允许您在看到需要时进一步扩展它。据我所知,当
进行多次嵌套检查时,guard不会有帮助,例如,如果TryAnotherCalculation
返回无
,我们将使用一些onemore计算
。这样,模式匹配就会变成嵌套的,这也不是很令人兴奋。活动模式似乎也是如此。如果我不高兴,请纠正我wrong@Rustam-你没有错。为了对抗这种缩进,您可能需要编写一个惰性序列,进行迭代,直到找到一个不是None
的值。像这样的嵌套链通常被称为“末日金字塔”,并在许多情况下出现,例如异步“未来”。计算表达式或绑定可以极大地简化代码。例如,请参见和。是的,我知道计算表达式,但从未使用过它们,因为我对F#相对较新。也许你可以提供一个在这种情况下如何使用它们的例子?我想它可能对许多程序员有用