Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 结构值初始化_F# - Fatal编程技术网

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

我从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
你如何处理类似的情况

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#相对较新。也许你可以提供一个在这种情况下如何使用它们的例子?我想它可能对许多程序员有用