【问题标题】:How does F# inline work?F# 内联如何工作?
【发布时间】:2011-05-23 17:39:20
【问题描述】:

据我了解,使用 F#,您可以使用 inline 关键字在调用站点执行类型特化。那就是::

val inline (+) : ^a -> ^b -> ^c
      when (^a or ^b) : (static member (+) : ^a * ^b -> ^c)

限制^a^b 必须具有像op_Addition 这样的静态成员,或者是内置原语之一,可用于填补空白。

因此,如果您有一个带有 + 的方法,并且传入一个 int 和一个 short 作为参数,它会将 + 解包到一条指令以使用 int 的内置原语,如果您传入一个 float 和一个字节,它使用浮点原语加法操作码。

这是如何在编译时完成的?如何在 CLR 中有一个方法来根据类型切换它使用的操作码或方法?

Reflection.Emit 可以实现这种行为吗? 我知道内联是在调用站点执行的,这是否意味着代码不适用于 C#?

【问题讨论】:

  • 我对内部的了解并不多,但它看起来像定义+运算符的F#源代码(C:\Program Files (x86)\FSharp-2.0.0.0\ source\fsharp\FSharp.Core\prim-types.fs 第 3527 行)在编译类型时打开参数类型并直接发出 IL 代码。

标签: c# f# inline


【解决方案1】:

正如inline 所建议的,代码在调用站点内联。在每个调用点,您都知道具体的类型参数^T,因此该类型的特定代码插入那里。

这是由 F# 编译器完成的,您不能在其他上下文(如 C# 或 Ref.Emit)中轻松完成。

F# 库有一些仍然可以被其他语言调用的内联函数,这些实现的运行时会根据运行时类型进行动态调度,参见例如F# Core 库代码中prim-types.fsAdditionDynamic 的代码,感受一下。

【讨论】:

  • 所以你说它基本上是一个精心设计的编译器技巧?如果我从 C# 调用 FSharpFunc<,>,我会得到想要的行为吗?
  • FSharpFunc(或实际上大多数类型)类型的任何实例都不是(也不能)是inlineinline 适用于方法和函数,在 F# 库中只有少数。大多数东西都可以从 C# 中正常调用,但是一些不支持动态调用的 F# inline 函数(如 sin)只能从 F# 中调用,因为 F# 编译器必须在调用站点内联代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-17
  • 2018-02-08
  • 1970-01-01
  • 1970-01-01
  • 2014-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多