[<literal>]与F#</literal>中的其他常量有何不同?

时间:2014-08-24 14:40:01

标签: f#

我对Literal关键字感到困惑,为什么在F#中需要它。

阅读文档,我觉得[<Literal>]用于定义一个常量,但是我对这个常量与F#中的所有其他常量的区别有点困惑。

  

可以使用标记标记为常量的值   文字属性。此属性具有导致值的效果   被编译为常量。

当我想到一个常数时,我会想到一些不可改变的东西......

let x = "a" + "b" //this is a immutable value, its value is constant
[<Literal>]
let y = "a" + "b" //this is also a immutable value, but why is this a special constant?

是否因为'普通'F#值被懒惰地评估而且[<Literal>]没有被懒惰地评估..?他们的意思是'编译为常数'..?或者还有别的东西吗?

3 个答案:

答案 0 :(得分:37)

在您的示例中,x是在运行时分配的不可变值(但不是懒惰地评估),而y是在编译期间分配的。例如,

let myDLL = "foo.dll"

[<DllImport(myDLL, CallingConvention = CallingConvention.Cdecl)>]
extern void HelloWorld()

不起作用,因为DllImport是一个属性,需要在编译期间知道myDLL的值。但是,这将有效:

[<Literal>]
let myDLL = "foo.dll"

[<DllImport(myDLL, CallingConvention = CallingConvention.Cdecl)>]
extern void HelloWorld()

答案 1 :(得分:19)

如果您来自C#背景,则可以将Literal值视为const字段,将非文字值视为readonly字段。同样的差异也适用。

答案 2 :(得分:10)

我认为更好的例子是match中发生的事情。

这不符合您的期望:

let t = 3
match q with
|t -> printfn "this always happens"
|_ -> printfn "this never happens" //and produces a compiler warning

另一方面:

[<Literal>]
let t = 3
match q with
|t -> printfn "q is 3"
|_ -> printfn "q isn't 3"

因此,Literal是编译时常量,我们可以将它用于模式匹配。