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