Funkcje śródwierszowe
Funkcje wbudowane to funkcje zintegrowane bezpośrednio z kodem wywołującym.
Korzystanie z funkcji wbudowanych
W przypadku używania parametrów typu statycznego wszystkie funkcje sparametryzowane przez parametry typu muszą być wbudowane. Gwarantuje to, że kompilator może rozpoznać te parametry typu. W przypadku używania zwykłych parametrów typu ogólnego nie ma takiego ograniczenia.
Poza włączaniem używania ograniczeń składowych funkcje wbudowane mogą być przydatne podczas optymalizowania kodu. Jednak nadmierne wykorzystanie funkcji wbudowanych może spowodować, że kod będzie mniej odporny na zmiany optymalizacji kompilatora i implementację funkcji biblioteki. Z tego powodu należy unikać używania wbudowanych funkcji do optymalizacji, chyba że wypróbowano wszystkie inne techniki optymalizacji. Tworzenie wbudowanej funkcji lub metody może czasami poprawić wydajność, ale nie zawsze jest to przypadek. W związku z tym należy również użyć pomiarów wydajności, aby sprawdzić, czy wprowadzanie dowolnej funkcji w tekście rzeczywiście ma pozytywny wpływ.
inline
Modyfikator można zastosować do funkcji na najwyższym poziomie, na poziomie modułu lub na poziomie metody w klasie.
Poniższy przykład kodu ilustruje funkcję śródliniową na najwyższym poziomie, metodę wystąpienia wbudowanego i śródliniową metodę statyczną.
let inline increment x = x + 1
type WrapInt32() =
member inline this.incrementByOne(x) = x + 1
static member inline Increment(x) = x + 1
Wbudowane funkcje i wnioskowanie typów
Obecność inline
wpływu na wnioskowanie typu. Jest to spowodowane tym, że funkcje wbudowane mogą mieć statycznie rozpoznane parametry typu, natomiast funkcje inne niż wbudowane nie mogą. Poniższy przykład kodu przedstawia przypadek, w którym inline
jest pomocna, ponieważ używasz funkcji, która ma statycznie rozpoznany parametr typu, float
operator konwersji.
let inline printAsFloatingPoint number =
printfn "%f" (float number)
inline
Bez modyfikatora wnioskowanie typu wymusza, aby funkcja przyjmować określony typ, w tym przypadku int
. Jednak w przypadku inline
modyfikatora funkcja jest również wnioskowana o statycznie rozpoznanym parametrze typu. inline
W przypadku modyfikatora typ jest wnioskowany jako następujący:
^a -> unit when ^a : (static member op_Explicit : ^a -> float)
Oznacza to, że funkcja akceptuje dowolny typ, który obsługuje konwersję na zmiennoprzecinkowy.
WbudowanyifLambda
Kompilator języka F# zawiera optymalizator, który wykonuje tworzenie podkreślinia kodu. Atrybut InlineIfLambda
umożliwia opcjonalne wskazanie kodu, że jeśli argument jest określany jako funkcja lambda, argument ten powinien być zawsze podsycony w lokacjach wywołań. Aby uzyskać więcej informacji, zobacz F# RFC FS-1098.
Rozważmy na przykład następującą iterateTwice
funkcję, aby przejść przez tablicę:
let inline iterateTwice ([<InlineIfLambda>] action) (array: 'T[]) =
for i = 0 to array.Length-1 do
action array[i]
for i = 0 to array.Length-1 do
action array[i]
Jeśli lokacja połączenia to:
let arr = [| 1.. 100 |]
let mutable sum = 0
arr |> iterateTwice (fun x ->
sum <- sum + x)
Następnie po podkreśliniu i innych optymalizacjach kod staje się:
let arr = [| 1..100 |]
let mutable sum = 0
for i = 0 to arr.Length - 1 do
sum <- sum + arr[i]
for i = 0 to arr.Length - 1 do
sum <- sum + arr[i]
Ta optymalizacja jest stosowana niezależnie od rozmiaru wyrażenia lambda. Ta funkcja może również służyć do implementowania wyrejestrowywania pętli i bardziej niezawodnych przekształceń podobnych.
Ostrzeżenie zgody (/warnon:3517
lub właściwość <WarnOn>3517</WarnOn>
) można włączyć, aby wskazać miejsca w kodzie, w których InlineIfLambda
argumenty nie są powiązane z wyrażeniami lambda w lokacjach wywołań. W normalnych sytuacjach to ostrzeżenie nie powinno być włączone. Jednak w niektórych rodzajach programowania o wysokiej wydajności może być przydatne zapewnienie, że cały kod jest wbudowany i spłaszczone.