Встраиваемые функции

Встроенные функции — это функции, интегрированные непосредственно в вызывающий код.

Использование встроенных функций

При использовании статических параметров типа все функции, параметризованные параметрами типа, должны быть встроенными. Это гарантирует, что компилятор может разрешить эти параметры типа. При использовании обычных параметров универсального типа такое ограничение отсутствует.

Кроме включения использования ограничений элементов, встроенные функции могут быть полезны при оптимизации кода. Однако чрезмерное использование встроенных функций может привести к тому, что ваш код будет менее устойчив к изменениям в оптимизации компилятора и реализации библиотечных функций. По этой причине следует избегать использования встроенных функций для оптимизации, если не были предприняты другие методы оптимизации. Создание встроенной функции или метода иногда может повысить производительность, но это не всегда так. Поэтому следует также использовать измерения производительности, чтобы убедиться в том, что выполнение любой заданной функции имеет положительный результат.

inlineМодификатор можно применять к функциям на верхнем уровне, на уровне модуля или на уровне метода в классе.

В следующем примере кода показана встроенная функция на верхнем уровне, встроенный метод экземпляра и встроенный статический метод.

let inline increment x = x + 1
type WrapInt32() =
    member inline this.incrementByOne(x) = x + 1
    static member inline Increment(x) = x + 1

Встроенные функции и вывод типов

Наличие inline влияет на вывод типа. Это обусловлено тем, что встроенные функции могут иметь статически разрешаемые параметры типа, тогда как невстроенные функции не могут. В следующем примере кода показан случай, когда используется inline функция с статически разрешаемым параметром типа, float оператором преобразования.

let inline printAsFloatingPoint number =
    printfn "%f" (float number)

Без inline модификатора вывод типа заставляет функцию принять конкретный тип, в данном случае int . Но с помощью inline модификатора функция также выводится для статического разрешаемого параметра типа. При использовании inline модификатора тип выводится следующим образом:

^a -> unit when ^a : (static member op_Explicit : ^a -> float)

Это означает, что функция принимает любой тип, поддерживающий преобразование в float.

инлинеифламбда

Компилятор F # включает в себя оптимизатор, который выполняет встраивание кода. InlineIfLambdaАтрибут позволяет коду дополнительно указать, что, если аргумент определен как лямбда-функция, этот аргумент всегда должен быть встроен в узлы вызова. Дополнительные сведения см. в разделе F # RFC FS-1098.

Например, рассмотрим следующую iterateTwice функцию для прохода по массиву:

let inline iterateTwice ([<InlineIfLambda>] action) (array: 'T[]) =
    for j = 0 to array.Length-1 do
        action array[j]
    for j = 0 to array.Length-1 do
        action array[j]

Если сайт вызова:

let arr = [| 1.. 100 |]
let mutable sum = 0
arr  |> iterateTwice (fun x ->
    sum <- sum + x)

После встраивания и других оптимизаций код выглядит следующим образом:

let arr = [| 1.. 100 |]
let mutable sum = 0
for j = 0 to array.Length-1 do
    sum <- array[i] + x
for j = 0 to array.Length-1 do
    sum <- array[i] + x

Эта оптимизация применяется независимо от размера вовлеченного лямбда-выражения. Эта функция также может использоваться для более надежной реализации циклов и аналогичных преобразований.

Предупреждение о /warnon:3517 включении (или свойство <WarnOn>3517</WarnOn> ) можно включить, чтобы указать места в коде InlineIfLambda , где аргументы не привязаны к лямбда-выражениям на сайтах вызовов. В обычных ситуациях это предупреждение не должно быть включено. Однако в некоторых видах высокопроизводительного программирования может быть полезно обеспечить встраивание и сведение всего кода.

См. также