Что делает FSharpFunc <> быстрее, чем Func <>? - PullRequest
22 голосов
/ 21 января 2010

Мне интересно узнать об улучшениях производительности, которые были сделаны для FSharpFunc <>. Это тот факт, что он не содержит нескольких делегатов, поэтому нет необходимости перебирать все ссылки при запуске вызова функции? Что-нибудь еще?

Ответы [ 2 ]

25 голосов
/ 22 января 2010

Я думаю, что основной причиной использования FSharpFunc<> вместо Func<> или любого другого делегата является то, что вы не можете создать класс, который наследовал бы от типа делегата (сначала это звучит разумно, но в .NET, фактически делегат - это просто какой-то особый класс, поэтому в принципе это возможно. Зачем это нужно?

Если вы пишете функцию на F #, то она (в относительно небольшом, но весьма важном случае) обрабатывается в форме карри. Например, int -> int -> int на самом деле является типом функции int -> (int -> int) (каррирование означает, что вы пишете функцию, используя только функции с одним параметром - если вы вызываете ее с первым аргументом, вы получите функцию в результате и сможете вызывать возвращаемая функция со вторым аргументом).

Если бы F # использовал делегатов, тип был бы что-то вроде Func<int, Func<int, int>>. Как упоминал Брайан, вызов 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 # должен объявить свой собственный тип, который можно использовать в качестве базового класса ...

12 голосов
/ 21 января 2010

(я думаю, что теперь они называются FSharpFunc, а не FastFunc.)

Он представлен как тип с одним абстрактным методом (Invoke), который, я думаю, позволяет избежать некоторых накладных расходов, которые вы получаете с настоящими делегатами. А для нескольких параметров карри он позволяет вам вызывать все параметры «сразу», а не по одному (например, чтобы f x y можно было вызывать в CLR как f(x,y) вместо f(x)(y).

Есть что-нибудь еще? Я не помню сейчас. Вы можете проверить исходный код в prim-types.fs в FSharp.Core в дистрибутиве исходного кода, который поставляется с выпуском CTP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...