Kotlin内連結関数の詳細解と実例
Kotlin内連結関数の詳細解と実例
概要
インライン関数を言う前に、まず関数の呼び出し手順を説明します。
ある関数を呼び出して実際にプログラムの実行順序をメモリに保存したアドレスに移し、関数のプログラム内容を実行し終わったら、その関数を実行する前の場所に戻します。このような移行操作は、転送前に現場を保護し、実行された住所を記憶し、転送後に現場を復元し、元の保存先に従って実行してください。つまり、一般的に言っているのは、スタックと出庫です。したがって、関数呼び出しには一定の時間と空間的なオーバヘッドが必要である。これらの関数体のコードは大きくなく、頻繁に呼び出される関数にとっては、この時間と空間の消耗が大きいです。
この性能消耗問題はどう解決しますか?この時にインライン関数を導入します。インライン関数とは、プログラムをコンパイルするときに、コンパイラがプログラムに現れるインライン関数の呼び出し式をインライン関数の関数体で直接置換します。明らかに、このようにして転送の問題が発生しないが、コンパイル時に関数体のコードをプログラムに置換するため、ターゲットプログラムのコード量を増加させ、さらに空間的なオーバーヘッドを増加させ、時間代理販売では関数呼出のように大きくならないので、ターゲットコードの増加を代価にして時間の節約と交換することができる。
オンライン
Kotlinでは、inline修飾子マークインライン関数を使用して、関数自体に影響を与えます。また、Lamband表現に影響を与えます。この両方は呼び出し先にインラインされます。
たとえば:
インライン関数のパラメータに複数のランバー表現がある場合、インラインの一部だけを望んでいます。関数の一部のパラメータにnoinlineタグを追加できます。
ローカルではないリターン(Non-local return)
Kotlinでは、名前のある関数または匿名関数を終了するためには、無限固定符の通常のreturn文を使用しています。これはLamda式を終了するにはラベルなしのreturnを使用しなければならないことを意味します。Lambada式は、強制的にその関数を含めることができないので、Lamband式では使用できません。
一部のインライン関数は、自分の関数の中で直接にランバー表現パラメータを呼び出すのではなく、他の実行環境によって呼び出すことができます。例えば、一部のオブジェクトやネスト関数を通じて。この場合、Lambada式では、非局所的な制御フローも禁止されます。この点を識別するために、Lambda表式パラメータは、crossinline修飾子を追加する必要があります。
概要
インライン関数を言う前に、まず関数の呼び出し手順を説明します。
ある関数を呼び出して実際にプログラムの実行順序をメモリに保存したアドレスに移し、関数のプログラム内容を実行し終わったら、その関数を実行する前の場所に戻します。このような移行操作は、転送前に現場を保護し、実行された住所を記憶し、転送後に現場を復元し、元の保存先に従って実行してください。つまり、一般的に言っているのは、スタックと出庫です。したがって、関数呼び出しには一定の時間と空間的なオーバヘッドが必要である。これらの関数体のコードは大きくなく、頻繁に呼び出される関数にとっては、この時間と空間の消耗が大きいです。
この性能消耗問題はどう解決しますか?この時にインライン関数を導入します。インライン関数とは、プログラムをコンパイルするときに、コンパイラがプログラムに現れるインライン関数の呼び出し式をインライン関数の関数体で直接置換します。明らかに、このようにして転送の問題が発生しないが、コンパイル時に関数体のコードをプログラムに置換するため、ターゲットプログラムのコード量を増加させ、さらに空間的なオーバーヘッドを増加させ、時間代理販売では関数呼出のように大きくならないので、ターゲットコードの増加を代価にして時間の節約と交換することができる。
オンライン
Kotlinでは、inline修飾子マークインライン関数を使用して、関数自体に影響を与えます。また、Lamband表現に影響を与えます。この両方は呼び出し先にインラインされます。
たとえば:
inline fun lock<T>(lock: Lock, body: () -> T): T {
// ...
}
コンパイラは直接に次のコードを生成してもいいです。パラメータの関数オブジェクトを作成する必要はなく、このパラメータ指向の関数を呼び出します。
l.lock()
try {
foo()
}
finally {
l.unlock()
}
noinlineインライン関数のパラメータに複数のランバー表現がある場合、インラインの一部だけを望んでいます。関数の一部のパラメータにnoinlineタグを追加できます。
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
// ...
}
インライン可能なLamban表現はインライン関数の内部でのみ呼び出されます。またはインライン可能なパラメータとして他の関数に伝達されますが、noinlineのLamban表現は私達の好きな方法で自由に使えます。ローカルではないリターン(Non-local return)
Kotlinでは、名前のある関数または匿名関数を終了するためには、無限固定符の通常のreturn文を使用しています。これはLamda式を終了するにはラベルなしのreturnを使用しなければならないことを意味します。Lambada式は、強制的にその関数を含めることができないので、Lamband式では使用できません。
fun foo() {
ordinaryFunction {
return // : `foo`
}
}
Lamban表現が転送される関数がインライン関数であれば、return文はインラインもできますので、returnは許可されます。
fun foo() {
inlineFunction {
return // OK: Lambda
}
}
注:一部のインライン関数は、自分の関数の中で直接にランバー表現パラメータを呼び出すのではなく、他の実行環境によって呼び出すことができます。例えば、一部のオブジェクトやネスト関数を通じて。この場合、Lambada式では、非局所的な制御フローも禁止されます。この点を識別するために、Lambda表式パラメータは、crossinline修飾子を追加する必要があります。
inline fun f(crossinline body: () -> Unit) {
val f = object: Runnable {
override fun run() = body()
}
// ...
}
読んでくれてありがとうございます。みなさんのご協力をお願いします。ありがとうございます。