什么使FSharpFunc<>快于Func<>?

时间:2010-01-21 17:25:29

标签: f# delegates

我很好奇为FSharpFunc<>所做的性能增强。 事实上它不包含多个委托,因此在触发函数调用时不需要遍历所有引用吗?还有什么吗?

2 个答案:

答案 0 :(得分:25)

我认为使用FSharpFunc<>而不是Func<>或任何其他委托的主要动机是你不能创建一个从委托类型继承的类(起初,这听起来很合理,但是在.NET中,委托实际上只是一些特殊的类,因此原则上可以允许这样做。为什么需要这个?

如果你在F#中编写一个函数,那么(在相对较少但非常重要的情况下)以curry形式处理。例如int -> int -> int实际上是一个函数类型int -> (int -> int)(currying意味着你只使用单个参数的函数编写一个函数 - 如果用第一个参数调用它,你将得到一个函数作为结果并且您可以使用第二个参数调用返回的函数)。

如果F#使用了委托,则类型将类似于Func<int, Func<int, int>>。正如Brian所提到的,调用f x y将被转换为两个调用:f(x)(y)。然而,这种调用是最常见的(仅指定一个参数称为部分函数应用程序)。因此,当F#编译这样的函数时,它会创建一个带有优化的invoke方法的继承类,以便可以将其作为f.Invoke(x, y)调用:

class @some_F#_name@ : Func<int, Func<int, int>> {
   public int Invoke(int arg1, int arg2) { /* optimized call */ }
}

不幸的是,通过继承标准Func(因为它是委托)来创建这样的类是不可能的,所以F#必须声明它自己的类型,它可以用作基类......

答案 1 :(得分:12)

(我认为它们现在称为FSharpFunc而不是FastFunc。)

它表示为具有单个抽象方法(Invoke)的类型,我认为这避免了使用真正委托获得的一些开销。对于多个curried参数,它使您能够“一次”调用所有参数而不是逐个调用(例如,以便{CL}可以f x y调用f(x,y)而不是f(x)(y) {1}}。

还有别的吗?我现在不记得了。您可以在CTP版本附带的源代码发行版中查看FSharp.Core中prim-types.fs中的源代码。