F#模块初始化的不同行为 [英] Different behaviour on F# module initialization
问题描述
我有以下F#程序:
open MyModule
printfn "%d" test
使用MyModule:
With MyModule being:
module MyModule
printfn "foo"
let test =
printfn "bar"
42
这将产生以下输出:
foo
bar
42
当我将MyModule更改为:
When I change MyModule to:
module MyModule
printfn "foo"
let test =
// printfn "bar" <-- note the comment!
42
...结果是:
42
为什么"foo"不再打印?
Why doesn't "foo" get printed anymore?
推荐答案
I think section 12.5.1 of the spec, Execution of Static Initializers, has your answer. Quoting the relevant bits:
文件的静态初始值设定项是在首次访问具有可观察到的初始值的值时执行的
the static initializer for the file is executed on first access of a value that has observable initialization
和
除模块中的以下定义外,所有定义均具有可观察到的初始化:
All definitions have observable initialization except for the following definitions in modules:
以下列表包括:
绑定到简单常量表达式的非可变,非线程局部值
Non-mutable, non-thread-local values that are bound to a simple constant expression
注释掉test
的第一行后,它成为一个常量表达式.因此,它不再触发静态初始化.
After commenting out the first line of test
, it becomes a constant expression. So therefore, it no longer triggers static initialization.
编辑
该规范未提供此行为的原理,但与C#相似.例如,在此代码中,永远不会发生静态初始化:
The spec doesn't provide the rationale for this behavior, but it's similar to C#'s. For example, in this code static initialization never occurs:
class Program {
static void Main(string[] args) {
Console.WriteLine(T.Integer);
Console.WriteLine(T.Null);
Console.WriteLine(T.Enum);
Console.Read();
}
}
static class T {
static T() {
Console.WriteLine("You won't see this.");
}
public const int Integer = 1;
public const string Null = null;
public const ConsoleKey Enum = ConsoleKey.Escape;
}
这篇关于F#模块初始化的不同行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!