Funzioni inline

Le funzioni inline sono funzioni integrate direttamente nel codice chiamante.

Uso di funzioni inline

Quando si usano parametri di tipo statico, tutte le funzioni con parametri di tipo devono essere inline. Ciò garantisce che il compilatore possa risolvere questi parametri di tipo. Quando si usano parametri di tipo generico ordinari, non esiste alcuna restrizione.

Oltre ad abilitare l'uso di vincoli membro, le funzioni inline possono essere utili per ottimizzare il codice. Tuttavia, l'uso eccessivo delle funzioni inline può causare una minore resistenza al codice alle modifiche apportate alle ottimizzazioni del compilatore e all'implementazione delle funzioni di libreria. Per questo motivo, è consigliabile evitare di usare funzioni inline per l'ottimizzazione, a meno che non si siano provate tutte le altre tecniche di ottimizzazione. La creazione di una funzione o di un metodo inline può talvolta migliorare le prestazioni, ma questo non è sempre il caso. Pertanto, è consigliabile usare anche le misurazioni delle prestazioni per verificare che la creazione di una determinata funzione inline abbia un effetto positivo.

Il inline modificatore può essere applicato alle funzioni al livello superiore, a livello di modulo o a livello di metodo in una classe.

Nell'esempio di codice seguente viene illustrata una funzione inline al livello superiore, un metodo di istanza inline e un metodo statico inline.

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

Funzioni inline e inferenza dei tipi

La presenza di influisce sull'inferenza del inline tipo. Ciò è dovuto al fatto che le funzioni inline possono avere parametri di tipo risolti in modo statico, mentre funzioni non inline non possono. L'esempio di codice seguente illustra un caso in cui inline è utile perché si usa una funzione con un parametro di tipo risolto in modo statico, l'operatore float di conversione.

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

Senza il modificatore, l'inferenza del inline tipo forza la funzione a accettare un tipo specifico, in questo caso int. Tuttavia, con il inline modificatore, la funzione viene dedotta anche per avere un parametro di tipo risolto in modo statico. Con il inline modificatore, il tipo viene dedotto come segue:

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

Ciò significa che la funzione accetta qualsiasi tipo che supporti una conversione in float.

InlineIfLambda

Il compilatore F# include un ottimizzatore che esegue l'inlining del codice. L'attributo InlineIfLambda consente al codice di indicare facoltativamente che, se un argomento è determinato come una funzione lambda, tale argomento deve essere sempre inlined nei siti di chiamata. Per altre informazioni, vedere F# RFC FS-1098.

Si consideri ad esempio la funzione seguente iterateTwice per attraversare una matrice:

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]

Se il sito di chiamata è:

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

Dopo l'inlining e altre ottimizzazioni, il codice diventa:

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] 

Questa ottimizzazione viene applicata indipendentemente dalle dimensioni dell'espressione lambda coinvolta. Questa funzionalità può essere usata anche per implementare l'annullamento della registrazione del ciclo e trasformazioni simili in modo più affidabile.

È possibile attivare un avviso di consenso esplicito (/warnon:3517 o proprietà <WarnOn>3517</WarnOn>) per indicare le posizioni nel codice in cui InlineIfLambda gli argomenti non sono associati alle espressioni lambda nei siti di chiamata. In situazioni normali, questo avviso non deve essere abilitato. Tuttavia, in alcuni tipi di programmazione ad alte prestazioni, può essere utile assicurarsi che tutto il codice sia inlined e appiattito.

Vedi anche