2017-08-18 1 views
11

私はthis questionを読みましたが、crossinlineキーワードに関するより根本的な質問があります。私は本当にどのような問題が解決しているのか、それがどのように解決するのかは分かりません。 the Kotlin Docsからコトリンのクロスインラインキーワード

、いくつかのインライン機能は、ローカルオブジェクトまたはネストされた関数として機能体から、しかし別の実行コンテキストから直接ではなく、パラメータとして渡されたラムダを呼び出すことが

注意。 の場合、では、非ローカル制御フローもラムダでは許可されません。この文は、私には曖昧である

[強調追加]

:、ラムダパラメータはcrossinline修飾子でマークする必要ことを示すために。まず、「そのような事件」が意味することを実際に描写するのに問題があります。私は問題が何であるかという一般的な考え方を持っていますが、その良い例を考え出すことはできません。

第2に、「それを示す」という言葉は、複数の方法で読むことができます。何を示す?その特定の場合は許可されていませんか?それはですか?与えられた関数定義における非局所的な制御フローが許可されている(または許可されていない)のですか?

要するに、これを実際に使用するためのコンテキスト、クライアントとの通信の使用方法、およびこのキーワードを適用すると期待される結果が何であるかを把握することができません。

答えて

10

まず、「そのような場合」が意味するものを実際に描くのに問題があります。私は問題が何であるかという一般的な考え方を持っていますが、その良い例を考え出すことはできません。

は、ここに例を示します

ここ
interface SomeInterface { 
    fun someFunction(): Unit 
} 

inline fun someInterfaceBy(f:() -> Unit): SomeInterface { 
    return object : SomeInterface { 
     override fun someFunction() = f() 
     //       ^^^ 
     // Error: Can't inline 'f' here: it may contain non-local returns. 
     // Add 'crossinline' modifier to parameter declaration 'f'. 
    } 
} 

someInterfaceBy { ... }に渡される関数はSomeInterfaceを実装する匿名クラス内でインライン化されます。 someInterfaceByの各呼び出しサイトの編集では、someFunction()の異なる実装で新しいクラスが作成されます。

、間違って行くことができるものを見るsomeInterfaceBy { ... }の呼び出しを検討する:インラインラムダ内部

fun foo() { 
    val i = someInterfaceBy { return } 
    // do something with `i` 
} 

を、return is non-local、実際fooからリターンを意味します。しかし、ラムダが呼び出されておらず、オブジェクトにリークされていないため、fooがすでに返された後、あるいは別のスレッドでさえもi.someFunction()(したがってラムダ)が呼び出されるとどうなりますか?

一般的に、「このような場合」がない自分の身体(事実、すなわち、アカウントに他のインライン関数を取る)であるが、非インラインラムダのように、彼らは宣言するいくつかの他の機能、内部でその機能のパラメータを呼び出すinline機能を意味匿名オブジェクト。


第二に、複数の方法を読み取ることができる "ということを示すため" というフレーズ。何を示す?特定のケースは許可されていませんか?それは許されているのですか?与えられた関数定義における非局所的な制御フローが許可されている(または許可されていない)のですか?

これは、私は、上記の問題はKotlinの言語設計に固定されている正確にどのようにある:inline関数はどこか、それはその場でと呼ばれるが、保存され、後に呼び出されていないことでしたどこにその機能的パラメータをインライン化する予定たびinline関数のパラメータはcrossinlineとマークされ、ここで渡されたラムダでは非ローカル制御フローが許可されないことを示します。

+0

したがって、 'crossinline'キーワードは、ラムダが関数内でラムダが使用される方法から決定的意味を持たない' return'キーワードを含むことを防ぎます(ローカルではない戻り値)。 – melston

+0

私はまた、ラベルでのリターンは 'crossinline'の使用によって影響を受けないと仮定します。 – melston

+0

@melston、はい、それは* local *である限りです。つまり、 'someList.forEach {item-> someCrossInline {return @ forEach item}}'は許されません。これは 'crossinline'ラムダのローカルではない戻り値ですが、' someList.forEach {item-> someCrossInline {return @someCrossInline item}} 'は大丈夫です(コメントに大きなコードをつけて申し訳ありません)。 – hotkey

関連する問題