[英]F# Code Execution Order
关于F#的另一个noob问题。
如果我有以下代码......
let ExeC =
printfn "c"
3
let ExeB b =
printfn "b"
2
let ExeA =
printfn "a"
1
printfn "Example %d " ExeA
printfn "Example %d " (ExeB 1)
printfn "Example %d " ExeC
输出如下......
c
a
Example 1
b
Example 2
Example 3
这里看起来很不寻常的是代码执行的顺序。在上一个问题中,Brian提到了一些关于表达式的问题,我希望有人可以解释一下这个问题。 几乎看起来编译器是智能地预先执行事物来计算值...但我不知道?
ExeA
和ExeC
不是函数,而是单个值。 编译器确保值按照在源文件中声明的顺序初始化,因此这里发生的是:
ExeC
初始化 ExeA
初始化 ExeA
的初始值打印Example 1
ExeB
函数被正常调用 ExeC
的初始值打印Example 3
如果你想让ExeA
和ExeC
真正变得懒惰 - 也就是说,控制它们的副作用何时运行 - 你可以把它们变成接受unit
函数:
let ExeC () =
printfn "c"
3
let ExeB b =
printfn "b"
2
let ExeA () =
printfn "a"
1
printfn "Example %d " (ExeA ())
printfn "Example %d " (ExeB 1)
printfn "Example %d " (ExeC ())
作为Tim回答的后续内容,我想你可能会对你偶然发现的事情有所了解。 在您的示例中,ExeC和ExeA利用通过词法作用域和闭包来组织代码的功能样式。 让我展示一个更有力的例子。
let calc n =
//...
let timesPieDiv4 =
let pie = 3.14
let pieDiv4 = pie/4.
n * pieDiv4
//...
在这里, timesPieDiv4
不是一个函数,但它的主体包含一系列子计算,这些子计算不会暴露给其余的calc
函数。 在像C#这样的语言中,你有两种选择,它们都不吸引我。 第一个选项是简单地在calc
主体中声明pie
和pieDiv4
,但是它们不太清楚它们是如何被使用的并且你弄脏你的变量空间。 另一种选择是将这些子计算分解为一个单独的私有辅助函数。 但是我不喜欢这样的功能,因为很多人很难分析你的复杂算法,因为你总是在寻找各种实现部分。 此外,它还有很多锅炉板代码和价值传递。 这就是为什么F#函数默认是“公共”的,词法作用域和闭包允许您在面向公众的函数中分层组织“私有”函数和值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.