【问题标题】:how does [<Literal>] differ from other constants in F#[<Literal>] 与 F# 中的其他常量有何不同
【发布时间】:2014-08-25 06:16:02
【问题描述】:

我对 Literal 关键字以及为什么它在 F# 中是必需的感到​​有些困惑。

阅读文档,我觉得[&lt;Literal&gt;] 用于定义一个常量,但是我有点困惑这个常量与 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# 值被延迟评估而[&lt;Literal&gt;] 没有被延迟评估..?这就是“编译为常量”的意思吗?还是有别的原因?

【问题讨论】:

    标签: f#


    【解决方案1】:

    在您的示例中,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()
    

    【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我认为一个更好的例子是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 是一个编译时常量,我们可以将它用于模式匹配。

      【讨论】:

      • 不幸的是,这个例子是区分大小写的。要按照描述的方式工作,文字标识符 t 必须以大写字母开头。对非文字版本使用大写字母会产生额外的编译器警告,但功能相同。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      • 2022-08-21
      相关资源
      最近更新 更多