我对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>]
没有被懒惰地评估..?他们的意思是'编译为常数'..?或者还有别的东西吗?
答案 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
是编译时常量,我们可以将它用于模式匹配。