【发布时间】:2013-05-03 23:41:31
【问题描述】:
我很好奇 FSharpFunc 的性能增强。 是不是它不包含多个委托,所以在触发函数调用时不需要循环所有引用?还有什么?
【问题讨论】:
我很好奇 FSharpFunc 的性能增强。 是不是它不包含多个委托,所以在触发函数调用时不需要循环所有引用?还有什么?
【问题讨论】:
我认为使用FSharpFunc<> 而不是Func<> 或任何其他委托的主要动机是你不能创建一个从委托类型继承的类(起初,这听起来很合理,但在.NET 中,委托实际上只是一些特殊的类,因此原则上可能允许这样做)。为什么需要这个?
如果您在 F# 中编写函数,那么它(在相对少数但非常重要的情况下)以柯里化形式处理。例如 int -> int -> int 实际上是一个函数类型 int -> (int -> int) (currying 意味着你只使用单个参数的函数编写一个函数 - 如果你用第一个参数调用它,你会得到一个函数作为结果,你可以调用带有第二个参数的返回函数)。
如果 F# 使用委托,则类型将类似于 Func<int, Func<int, int>>。正如 Brian 提到的,调用 f x y 将被转换为两个调用:f(x)(y)。然而,这种调用是最常见的(仅指定一个参数称为部分函数应用程序)。所以,当 F# 编译这样的函数时,它会创建一个带有优化的调用方法的继承类,这样就可以将其调用为f.Invoke(x, y):
class @some_F#_name@ : Func<int, Func<int, int>> {
public int Invoke(int arg1, int arg2) { /* optimized call */ }
}
不幸的是,不可能通过继承标准Func(因为它是一个委托)来创建这样的类,所以 F# 必须声明自己的类型,它可以用作基类...
【讨论】:
Func<...> 的方法,以使 C# 互操作尽可能顺利。
(我认为它们现在被称为 FSharpFunc 而不是 FastFunc。)
它表示为具有单个抽象方法 (Invoke) 的类型,我认为这可以避免使用真正的委托时产生的一些开销。对于多个 curried 参数,它使您能够“一次”而不是一个一个地调用所有参数(例如,f x y 可以在 CLR 上调用为f(x,y) 而不是f(x)(y)。
还有别的吗?我现在不记得了。您可以在 CTP 版本附带的源代码分发中查看 FSharp.Core 中 prim-types.fs 中的源代码。
【讨论】: