F# 初学者在多个相关名称上使用 let

F# beginner using let on multiple dependent names

我讨厌问这样一个菜鸟问题,但我在网上搜索了高低——这实际上是我的第一天。

以下 VBA 摘录分配两个变量,其中第一个变量输入第二个变量(此代码来自 www.spreadsheetadvice.com):

If zabs <= 12.7 Then
    ...
    If zabs <= 1.28 Then
        Temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
        Q = a0 - zabs * (a1 - a2 * y / Temp)
    Else
        Temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
        Q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
    End If
Else ...

我正在尝试在 F# 中复制它——不使用可变变量。这有效:

    let Temp = 
        if zabs <= 1.28 then
            y + a3 - a4 / (y + a5 + a6 / (y + a7))
        elif zabs <= 12.7 then
            (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
        else
            0.0

    let Q = 
        if zabs <= 1.28 then
            a0 - zabs * (a1 - a2 * y / Temp)
        elif zabs <= 12.7 then
            pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
        else
            0.0

但我不喜欢将两个相关变量分开——或重复 If 语句。这行不通,但已经很接近了:

    let Temp, Q = 
        if zabs <= 1.28 then
            y + a3 - a4 / (y + a5 + a6 / (y + a7)),
            a0 - zabs * (a1 - a2 * y / Temp)
        elif zabs <= 12.7 then
            (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11)))),
            pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
        else
            0.0,
            0.0

我花了一段时间才弄清楚第 3、6 和 9 行的逗号(如果它们确实正确的话)。但是编译器认为我在分配之前尝试使用 Temp。我假设,或者希望,我只是缺少一个简单的习语。

这个有效:

let Temp, Q = 
    if zabs <= 1.28 then
        let temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
        let q = a0 - zabs * (a1 - a2 * y / temp)
        temp, q
    elif zabs <= 12.7 then
        let temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
        let q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / temp)))
        temp, q
    else
        0.0, 0.0

It took me a while to figure out the commas on the 3rd, 6th, and 9th lines (if they are in fact right). But the compiler thinks I am trying to use Temp before it is assigned. I assume, or hope, I'm just missing a simple idiom.

是的,你缺少语言的基础知识,你必须加上逗号,因为你声明了一个 tuple 所以你必须绑定一个 'a * 'b

类型的值

我建议使用 模式匹配,这是 F#(和其他函数式语言)最强大的功能之一 - https://msdn.microsoft.com/en-us/library/dd547125.aspx

let yourfunc zabs = 
    match zabs with
    | x when x <= 1.28   -> let temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
                            let q = a0 - zabs * (a1 - a2 * y / temp)
                            temp, q
    | x when x <= 12.7   -> let temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
                            let q = pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / temp)))
                            temp, q
    | _ -> 0.0,0.0

我想我犯了一个简单的错误:因为 Temp 是临时的并且从属于 Q,所以 Temp 应该声明为 Q 声明的局部范围,而不是与 Q 相同的范围。弄清楚了,我认为使用 If 和使用 Match 效果一样好。但是 Match 可能更加地道(感谢 Alessandro)。因此:

    let Q =             
        match zabs with
        | i when i <= 1.28 ->
            let Temp = y + a3 - a4 / (y + a5 + a6 / (y + a7))
            a0 - zabs * (a1 - a2 * y / Temp)
        | i when i <= 12.7 ->
            let Temp = (zabs - b5 + b6 / (zabs + b7 - b8 / (zabs + b9 + b10 / (zabs + b11))))
            pdF / (zabs - b1 + (b2 / (zabs + b3 + b4 / Temp)))
        | _ ->
            0.0

所以现在我一定要做出两个声明,它们确实需要在不久的将来具有相同的范围,然后再次回到类似的情况...