F#模块初始化的不同行为 [英] Different behaviour on F# module initialization

查看:62
本文介绍了F#模块初始化的不同行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下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?

推荐答案

我认为规范的第12.5.1节

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆