Fonctions inline
Les fonctions inline sont des fonctions intégrées directement dans le code appelant.
Utilisation des fonctions inline
Quand vous utilisez des paramètres de type statiques, toutes les fonctions paramétrisées par des paramètres de type doivent être inline. Cela permet au compilateur de résoudre ces paramètres de type. Quand vous utilisez des paramètres de type génériques ordinaires, il n’y a pas de restriction de ce genre.
En plus d’activer l’utilisation des contraintes de membre, les fonctions inline peuvent être utiles pour optimiser le code. Toutefois, la surutilisation des fonctions inline peut rendre votre code moins résistant aux changements des optimisations du compilateur et à l’implémentation des fonctions de bibliothèque. Pour cette raison, vous devez éviter d’utiliser des fonctions inline pour l’optimisation, sauf si vous avez essayé toutes les autres techniques d’optimisation. L’utilisation d’une fonction ou d’une méthode inline peut parfois améliorer les performances, mais ce n’est pas toujours le cas. Par conséquent, vous devez également utiliser des mesures de performances pour vérifier que l’utilisation d’une fonction inline donnée a effectivement un effet positif.
Le modificateur inline
peut être appliqué aux fonctions au niveau supérieur, au niveau du module ou au niveau de la méthode dans une classe.
L’exemple de code suivant illustre une fonction inline au niveau supérieur, une méthode d’instance inline et une méthode statique inline.
let inline increment x = x + 1
type WrapInt32() =
member inline this.incrementByOne(x) = x + 1
static member inline Increment(x) = x + 1
Fonctions inline et inférence de type
La présence de inline
affecte l’inférence de type. C’est parce que les fonctions inline peuvent avoir des paramètres de type résolus de manière statique, contrairement aux fonctions non inline. L’exemple de code suivant montre un cas où inline
est utile, car vous utilisez une fonction qui a un paramètre de type résolu statiquement, l’opérateur de conversion float
.
let inline printAsFloatingPoint number =
printfn "%f" (float number)
Sans le modificateur inline
, l’inférence de type force la fonction à prendre un type spécifique, dans ce cas int
. Mais avec le modificateur inline
, la fonction a également par déduction un paramètre de type résolu de manière statique. Avec le modificateur inline
, le type suivant est déduit :
^a -> unit when ^a : (static member op_Explicit : ^a -> float)
Cela signifie que la fonction accepte tout type qui prend en charge une conversion en float.
InlineIfLambda
Le compilateur F# comprend un optimiseur qui procède à l’inlining du code. L’attribut InlineIfLambda
permet au code d’indiquer éventuellement que, si un argument est identifié comme une fonction lambda, cet argument doit toujours être inline sur les sites d’appel. Pour plus d’informations, consultez F# RFC FS-1098.
Par exemple, examinons la fonction iterateTwice
suivante pour parcourir un tableau :
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]
Si le site d’appel est :
let arr = [| 1.. 100 |]
let mutable sum = 0
arr |> iterateTwice (fun x ->
sum <- sum + x)
Après l’inlining et d’autres optimisations, le code devient :
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]
Cette optimisation est appliquée quelle que soit la taille de l’expression lambda concernée. Cette fonctionnalité peut également être utilisée pour implémenter un déroulement des boucles et des transformations similaires de manière plus fiable.
Un avertissement (/warnon:3517
ou la propriété <WarnOn>3517</WarnOn>
) peut être activé pour indiquer les emplacements dans votre code où les arguments InlineIfLambda
ne sont pas liés aux expressions lambda sur les sites d’appel. En situation normale, cet avertissement ne doit pas être activé. Toutefois, dans certains types de programmation hautes performances, il peut être utile de s’assurer que tout le code est inlined et aplati.