web-dev-qa-db-ja.com

kotlinでジェネリックスを使用してラムダを作成する方法は?

ラムダを書くことができますid_Intおよびid_Boolean明示的なタイプ。そして、typeパラメーターを使用して関数identityを記述できます。 typeパラメーターを使用してラムダを記述できますか?

fun testFuncInt(f: (Int) -> Int): Int = f(1) + 2

val id_Int = { x: Int -> x }

fun testFuncBoolean(f: (Boolean) -> Boolean): Boolean = !f(false)

val id_Boolean = { x: Boolean -> x }

fun <T> identity(x: T) = x

fun main(args: Array<String>) {
    println(testFuncInt(id_Int))
    println(testFuncInt(::identity))
    println(testFuncBoolean(id_Boolean))
    println(testFuncBoolean(::identity))
}
11
xiang

Kotlinは、クラスレベルでその型を宣言せずにジェネリックプロパティを宣言することをサポートしていません( 参照 )が、目的の型に対応するラムダを返す関数を使用して行うことができます。

fun main(args: Array<String>) {
    println(testFuncBoolean(id()))
    println(testFuncInt(id()))
}

fun <T> id(): (T) -> T = { it }

fun testFuncInt(f: (Int) -> Int): Int = f(1) + 2
fun testFuncBoolean(f: (Boolean) -> Boolean): Boolean = !f(false)

いいえ、しかしあなたは一般的にそうする必要はありません。ラムダには宣言がないため(これは一種のポイントです)、本質的には関数に渡すことができる式であり、val id_Boolean = { x: Boolean -> x }を実行するときと同じように、val/varに格納しますがタイプは、式の場合と同じように実際に処理されます。

ここでの呼び出しは正しい型に解決されます。これは、関数がIntを受け取ってIntを返す関数と、Booleanを受け取ってBoolean

testFuncInt({ x -> x }) // x is an Int
testFuncInt({ it })     // it is the default argument
testFuncInt { x -> x }  // as top one, Kotlin's syntactic sugar

ここで重要なことは、ラムダ式がまだ型安全性を提供することです。つまり、このようなことをした場合です。

fun <T> foo(x: T, lambda: (T) -> Boolean): Boolean = lambda(x)
foo(42, { x -> x })   // oops, lambda takes a T and returns a T

lambdaの型がfooが期待するものと一致しないため、これはコンパイラエラーをトリガーします。つまり、fooIntをラムダに渡し、 Boolean戻る。一方、これを行う場合

foo(123, { it == 42 })
foo(123) { it == 42 }   // equivalent to above

戻り値の型は実際にはBooleanであると推定されます。これは、比較演算の結果が評価されるものであり、123と42は同じ型であるため、lambdaの型は実際にはfooが期待します。

2
Andrej

ジェネリックスでラムダを書くことはできません、なぜ公式ドキュメントから取られた次の段落はそれをすべて言います。

ラムダ式または無名関数は「関数リテラル」です。つまり、宣言されていないが、式としてすぐに渡される関数です。

ラムダ式または関数は宣言されておらず、無名関数です。

しかし、最終的には、関数型をジェネリックとして宣言することで同じことを行います。その仕事をするラムダ式を渡すことができます。

fun testFuncInt(f: (Int) -> Int): Int = f(1) + 2 

あなたはそれを次のように呼ぶことができます:testFuncInt{ a -> a }またはtestFuncInt{ it }

つまり、最終的に同じことを実行します(型パラメーターを持つラムダ)が、ラムダは式または無名関数であるため、そのような用語はありません。

それが役に立てば幸い。

2
chandil03