Kotlinでは、一つの式からなる関数は
fun add(x: Int, y: Int): Int = x + y
のように明示的なreturnを必要としません。次のように複数の式からなる関数定義ではreturnが必須となります。
fun printAndAdd(x: Int, y: Int): Int { val k = x + y println(k) return k //必須 }
この制限の理由について、Kotlinのリファレンスでは
Kotlin does not infer return types for functions with block bodies because such functions may have complex control flow in the body, and the return type will be non-obvious to the reader (and sometimes even for the compiler).
と書いているのですが(強調は筆者による)、変な話です。何故かというと、ラムダ式は複数の式を持てるのに、ちゃんと型を推論できているからです。
一方、Kotlinにはinline
という修飾子を関数につけることができて、これは、inline
指定された関数を呼び出すときに、インライン展開させるように指示するものです。たとえば、
inline add(x: Int, y: Int): Int = x + y println(add(1, 2))
とした場合、これは
println(1 + 2)
と同じコードとなることが期待できます。これを利用して、ブロックからなる関数定義でも、明示的にreturnを書かなくてよいようにする小技を思いついたのでご紹介します。方法は簡単で、
inline fun <T> block(body: () -> T): T { return body() }
という関数を定義して、
fun printAndAdd(x: Int, y: Int): Int = block { val k = x + y println(k) k //return不要 }
のように、=
に続けて、定義したblock
関数を呼び出すだけです。実に簡単です。さて、こうした場合の実行性能ですが、一つ定義するごとに、getstatic
命令とその直後にpop
命令が余分に追加されていました。両方とも命令の実行コストは非常に軽いことが予測されますし、無意味な命令としてJVMのJITコンパイラが除去してくれる可能性もあります。いずれにせよ、通常気にする必要のあるオーバーヘッドは発生しません。
現在、そういう制御フローに関する小物関数を集めたライブラリを作ろうかななどと考えています(考えるだけでやるとは言っていない)。