Infogade funktioner
Infogade funktioner är funktioner som är integrerade direkt i anropskoden.
Använda infogade funktioner
När du använder parametrar av statisk typ måste alla funktioner som parametriseras efter typparametrar vara infogade. Detta garanterar att kompilatorn kan matcha dessa typparametrar. När du använder vanliga allmänna typparametrar finns det ingen sådan begränsning.
Förutom att aktivera användning av medlemsbegränsningar kan infogade funktioner vara användbara när du optimerar kod. Överanvändning av infogade funktioner kan dock göra att koden blir mindre motståndskraftig mot ändringar i kompilatoroptimeringar och implementering av biblioteksfunktioner. Därför bör du undvika att använda infogade funktioner för optimering om du inte har provat alla andra optimeringstekniker. Att göra en funktion eller metod infogad kan ibland förbättra prestandan, men så är inte alltid fallet. Därför bör du också använda prestandamätningar för att kontrollera att det faktiskt har en positiv effekt att göra en viss funktion infogad.
Modifieraren inline
kan tillämpas på funktioner på den översta nivån, på modulnivå eller på metodnivå i en klass.
I följande kodexempel visas en infogad funktion på den översta nivån, en infogad instansmetod och en infogad statisk metod.
let inline increment x = x + 1
type WrapInt32() =
member inline this.incrementByOne(x) = x + 1
static member inline Increment(x) = x + 1
Infogade funktioner och typinferens
Förekomsten av inline
påverkar typinferens. Detta beror på att infogade funktioner kan ha statiskt lösta typparametrar, medan icke-infogade funktioner inte kan. I följande kodexempel visas ett fall där inline
är användbart eftersom du använder en funktion som har en statiskt löst typparameter, konverteringsoperatorn float
.
let inline printAsFloatingPoint number =
printfn "%f" (float number)
inline
Utan modifieraren tvingar typinferens funktionen att ta en viss typ, i det här fallet int
. Men med inline
modifieraren härleds funktionen också till att ha en statiskt löst typparameter. inline
Med modifieraren härleds typen till följande:
^a -> unit when ^a : (static member op_Explicit : ^a -> float)
Det innebär att funktionen accepterar alla typer som stöder en konvertering till flyttal.
InlineIfLambda
F#-kompilatorn innehåller en optimerare som utför inlinning av kod. Attributet InlineIfLambda
tillåter att kod kan ange att om ett argument fastställs vara en lambda-funktion, bör argumentet i sig alltid vara inlindat på anropsplatser. Mer information finns i F# RFC FS-1098.
Tänk dig till exempel följande iterateTwice
funktion för att korsa en matris:
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]
Om samtalswebbplatsen är:
let arr = [| 1.. 100 |]
let mutable sum = 0
arr |> iterateTwice (fun x ->
sum <- sum + x)
Efter inlining och andra optimeringar blir koden:
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]
Den här optimeringen tillämpas oavsett storleken på lambda-uttrycket. Den här funktionen kan också användas för att implementera loop-avregistrering och liknande transformeringar på ett mer tillförlitligt sätt.
En opt-in-varning (/warnon:3517
eller egenskap <WarnOn>3517</WarnOn>
) kan aktiveras för att ange platser i koden där InlineIfLambda
argument inte är bundna till lambda-uttryck på anropsplatser. I normala situationer bör den här varningen inte aktiveras. I vissa typer av programmering med höga prestanda kan det dock vara användbart att se till att all kod är inlindad och utplattad.