为什么文字默认不是常量?

Why do literals not const by default?

如果 F# 鼓励编写不可变的急切求值数据,为什么 F# 不强制简单的 let 绑定默认为 const

我需要显式写入 [<Literal>] 属性。例如:

module ConstVsStaticReadOnly =

    [<Literal>]
    let ConstInt32 = 1

    [<Literal>]
    let ConstString = "A" + "B" + "C"

    let staticReadOnlyBoolean = true

当您在 .NET 中使用 const 时,所有对它的引用都会在编译时替换为它的值。

听起来不错,直到您意识到它不仅限于定义常量的程序集。引用它的其他程序集也会在编译时复制常量的值。

你可以在一个简单的例子中看到结果:

使用单个模块创建新的 F# 库项目

module ConstTest 

let [<Literal>] ConstInt = 1
let NotConstInt = ConstInt

然后是一个引用库的控制台应用程序

[<EntryPoint>]
let main argv = 
    printfn "%A %A" ConstTest.ConstInt ConstTest.NotConstInt
    0

当 运行 时,它打印 1 1 - 正如预期的那样。

现在修改库中的常量

module ConstTest 

let [<Literal>] ConstInt = 2
let NotConstInt = ConstInt

构建库(但不是控制台应用程序!),将 dll 复制到控制台应用程序文件夹和 运行 应用程序。它打印 1 2。如果您不知道这种行为,那将是一个惊喜。

一旦创建了 public 常数,它就应该 永远不会 改变。这就是编译器不会隐式创建常量的原因。