インライン関数

"インライン関数" とは、呼び出しコードに直接統合されている関数です。

インライン関数の使用

静的型パラメーターを使用する場合、型パラメーターによってパラメーター化される関数はインラインである必要があります。 これにより、コンパイラでこれらの型パラメーターを解決できることが保証されます。 通常のジェネリック型パラメーターを使用する場合、このような制限はありません。

インライン関数は、メンバー制約の使用を有効にするだけでなく、コードの最適化にも役立ちます。 ただし、インライン関数を過剰に使用すると、コンパイラの最適化およびライブラリ関数の実装の変更に対してコードの抵抗力が低下する可能性があります。 そのため、他のすべての最適化手法を試したのでない限り、最適化にインライン関数を使用しないようにしてください。 関数またはメソッドをインラインにするとパフォーマンスが向上する場合がありますが、常にそうであるとは限りません。 したがって、特定の関数をインラインにすることに実際に好ましい効果があることを確認するために、パフォーマンス測定も使用する必要があります。

inline 修飾子は、クラスの最上位レベル、モジュール レベル、またはメソッド レベルの関数に適用できます。

次のコード例は、最上位レベルのインライン関数、インライン インスタンス メソッド、インライン静的メソッドを示しています。

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

インライン関数と型の推定

inline があると型の推定に影響します。 これは、インライン関数は静的に解決される型パラメーターを持つことができるのに対し、非インライン関数はそうできないためです。 次のコード例は、静的に解決される型パラメーターを持つ関数 (float 変換演算子) を使用しているため、inline が役に立つケースを示しています。

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

inline 修飾子を使用しない場合、型の推定により、特定の型が関数に強制されます (この場合は int)。 しかし、inline 修飾子を使用すると、静的に解決される型パラメーターを持つものとして関数が推定されることにもなります。 inline 修飾子を使用すると、型は次のように推定されます。

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

これは、float への変換をサポートする任意の型を関数に指定できることを意味します。

InlineIfLambda

F# コンパイラには、コードのインライン化を実行するオプティマイザーが含まれています。 InlineIfLambda 属性では、引数がラムダ関数であると判断された場合、その引数自体を呼び出しサイトで常にインライン化する必要があることを、必要に応じてコードで示すことができます。 詳細については、「F# RFC FS-1098」を参照してください。

たとえば、配列を走査するための次の iterateTwice 関数があるとします。

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]

呼び出しサイトが次のような場合:

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

インライン化とその他の最適化の後、コードは次のようになります。

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] 

この最適化は、関連するラムダ式のサイズに関係なく適用されます。 この機能を使用して、ループのアンロールや同様の変換をより確実に実装することもできます。

オプトイン警告 (/warnon:3517 またはプロパティ <WarnOn>3517</WarnOn>) をオンにすると、呼び出しサイトで InlineIfLambda 引数がラムダ式にバインドされていないコード内の場所を示すことができます。 通常の状況では、この警告を有効にしないでください。 しかし、特定の種類の高パフォーマンス プログラミングでは、すべてのコードが確実にインライン化およびフラット化されるようにするのに役立つ場合があります。

関連項目