@file:Suppress( "USELESS_CAST", "unused", "DEPRECATED_IDENTITY_EQUALS", "UNUSED_VARIABLE", "UNUSED_VALUE", "ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE", "VARIABLE_WITH_REDUNDANT_INITIALIZER", "ReplaceCallWithComparison" ) package jp.juggler.subwaytooter import org.junit.Test //import kotlin.test.* typealias TestLambdaCallback = (x: Int) -> Int class TestKotlinFeature { private val CODE_A = 1 private val CODE_A2 = 2 // コンパイラに予測できない方法でIntの10を生成する private fun generate10A(): Int { return ("1" + "0").toInt() } // コンパイラに予測できない方法でIntの10を生成する private fun generate10B(): Int { var i = 0 while (true) { ++i if (i % 5 == 0 && i % 2 == 0) return i } } interface MyKotlinInterface { fun method(x: Int): Int } @Test fun testLambda() { // 定義例(文脈あり) println(10.let { x -> x * x }) println(10) // 定義例(文脈不明) val a = { println("testLambda") } // 参照型の定義 val ref: (x: Int) -> Int = { it * it } // 参照型の呼び出し println(ref(10)) // 参照型の定義(Nullable) @Suppress("RedundantNullableReturnType") val refNullable: TestLambdaCallback? = { it * it } if (refNullable != null) { refNullable(10) } } @Test fun testAnonymousFunction() { // 定義例(文脈あり) println(10.let(fun(x: Int) = x * x)) println(10) // 定義例(文脈不明) val a = fun(x: Int) = x * x // 参照型の定義 val ref: (x: Int) -> Int = a // 参照型の呼び出し println(ref(10)) // 参照型の定義(Nullable) @Suppress("RedundantNullableReturnType") val refNullable: TestLambdaCallback? = fun(i: Int) = i * i if (refNullable != null) { refNullable(10) } } @Test fun testObjectExpression() { // 定義例(文脈あり) @Suppress("UnnecessaryAbstractClass") abstract class Base { abstract fun method(x: Int): Int } val a = object : Base() { override fun method(x: Int): Int { return x * x } } // 定義例(文脈の有無で変化しない) // 参照型の定義 val ref: Base = a // 参照型の定義(Nullable) @Suppress("RedundantNullableReturnType") val refNullable: Base? = a if (refNullable != null) { val v = refNullable.method(10) println("OE v=$v") } fun caller(b: Base) { val v = b.method(10) println("OE b $v") } caller(object : Base() { override fun method(x: Int): Int { return x * x * x } }) } private fun member(x: Int) = x * x @Test fun testMemberReference() { fun caller(a: (receiver: TestKotlinFeature, x: Int) -> Int) { val v = a(this, 10) println("testMemberReference caller $v") } caller(TestKotlinFeature::member) val b = TestKotlinFeature::member val a: (receiver: TestKotlinFeature, x: Int) -> Int = TestKotlinFeature::member } fun methodNotInline(callback: (x: Int) -> Int): Int { return callback(3) } inline fun methodInline(callback: (x: Int) -> Int): Int { return callback(5) } @Test fun testReturn() { // loop@ for( i in 1..2) { // // 関数の引数以外の場所で定義したラムダ式 // var x = { x : Int -> // break // コンパイルエラー // break@loop // コンパイルエラー // // return // コンパイルエラー // x * x // }(10) // println("testReturn A:$x") // // // 非インライン関数の引数として定義したラムダ式 // x = methodNotInline { x : Int -> // break // コンパイルエラー // break@loop // コンパイルエラー // // // return // コンパイルエラー // // return@methodNotInline x * x // } // println("testReturn B:$x") // // // インライン関数の引数として定義したラムダ式 // methodInline { x : Int -> // break // コンパイルエラー // break@loop // コンパイルエラー // // return 10 // できる // // return@methodInline 10 // できる // } // } } private fun A.letNotInline(code: (A) -> B): B { return code(this) } @Test fun testInline0() { var result: Int val n = 11 for (i in 1..10) { println(n.letNotInline { v -> val rv = v * i result = rv rv }) } } @Test fun testInline1() { var result: Int val n = 12 for (i in 1..10) { println(n.let { v -> val rv = v * i result = rv rv }) } } @Test fun testInline2() { var result: Int val n = 13 for (i in 1..10) { val rv = n * i result = rv println(rv) } } @Test fun testRawArray() { // サイズを指定して生成 val a = IntArray(4) for (i in a.indices) { a[i] = i * 2 } println(a.joinToString(",")) // サイズと初期化ラムダを指定して生成 val b = IntArray(4) { index -> index * 3 } println(b.joinToString(",")) // 可変長引数で初期化するライブラリ関数 val b2 = intArrayOf(0, 1, 2, 3) // 参照型の配列だと初期化ラムダが必須 val c = Array(4) { (it * 4).toString() } println(c.joinToString(",")) val d = Array(4) { if (it % 2 == 0) null else (it * 5).toString() } println(d.joinToString(",")) // ラムダ式の戻り値の型から配列の型パラメータが推測される val e = Array(4) { if (it % 2 == 0) null else (it * 6).toString() } println(e.joinToString(",")) // 可変長引数で初期化するライブラリ関数 val e2 = arrayOf(null, 1, null, 2) } @Test fun testOutProjectedType() { fun foo(args: Array) { val sb = StringBuilder() for (s in args) { if (sb.isNotEmpty()) sb.append(',') sb .append(s.toString()) .append('#') .append(s.javaClass.simpleName) } println(sb) println(args.contains(6)) // 禁止されていない。inポジションって何だ…? // args[0]=6 //禁止されている } foo(arrayOf(1, 2, 3)) foo(arrayOf(1f, 2f, 3f)) } }