関数
// 普通の書き方
fun square(x: Int): Int {
return x * x
}
// 簡略した
fun square(x: Int): Int = x * x
// 型推論もできるので、推論できる場合は戻り値の型も省略可能
fun square(x: Int) = x * x
たとえ簡単で1行で表現できたとしても{}
で囲ったほうが統一感が出ていいかもと思っている
現時点での気持ちなので、「短いは正義!!」とか気持ちが変わるかもしれない。
名前付き引数
fun square(x: Int): Int {
return x * x
}
val squared = square(x = 1)
// 最新のIntelliJ IDEA とか Android Studioは引数のラベルを表示してくれるけど
// こう書いたほうがGit上での差分を見るときには読みやすそう
// Swiftはこのラベルが自動的に表示されてくれるからそのほうがうれしい
// ラベルの順番はどうでもいい
fun add(x: Int, y: Int) = x + y
val added = add(y = 1, x = 2)
デフォルト引数
fun printHello(name: String = "guest") = println("hello, $name")
printHello() // hello, guest
printHello(name = "hicka04") // hello, hicka04
可変長変数
-
vararg
を引数の前につけるだけで、引数を配列として受け取ることができるようになる - 可変長変数は1つの関数につき1つまで
fun sum(vararg ints: Int): Int {
var sum = 0
for (i in ints) {
sum += i
}
return sum
}
println(sum(1, 2, 3)) // 6
// 配列を渡すときは`*`を先頭につける必要がある
println(sum(ints = *intArrayOf(1, 2, 3)))
再帰呼び出し
使わないパターン
fun sum(numbers: List<Long>): Long {
var sum = 0L
for (n in numbers) {
sum += n
}
return sum
}
使うパターン
リストが空になるまで「最初の要素」と「最初の要素以外のリストの合計」を出す
fun sum(numbers: List<Long>): Long =
if (numbers.isEmpty()) 0
else numbers.first() + sum(numbers.drop(1))
注意点
- 再帰呼び出しの回数が多いとスタックを食いつぶし、スタックオーバーフローでクラッシュする可能性がある
- スタックを消費しないように再帰呼び出しを最適化してくれる仕組みがある
→TCO(Tail Call Optimization, 末尾呼び出し最適化) - 再帰呼び出しを関数の最後の計算になるように変更する必要がある
tailrec fun sum(numbers: List<Long>, accumulator: Long = 0): Long =
if (numbers.isEmpty()) accumulator
else sum(numbers.drop(1), accumulator + numbers.first())
ローカル関数
- 関数内に別の関数を定義すること
- スコープを限定的にしたいときなど
- 上記の
sum(numbers:accumulator:)
はいかなる場合においてもaccumulator
が0になっていてほしいが、デフォルト引数で渡しているだけなので、初期値0の縛りをかけたい
// go(numbers:accumulator:)はさっきのsum(numbers:accumulator:)と同じ
// このsumを呼び出す側にはaccumulatorが見えなくなった
fun sum(numbers: List<Long>): Long {
tailrec fun go(numbers: List<Long>, accumulator: Long = 0): Long =
if (numbers.isEmpty()) accumulator
else go(numbers.drop(1), accumulator + numbers.first())
return go(numbers, 0)
}
値を返さない関数
- 返り値の型に
Unit
を指定する - Kotlin:
Unit
== Java:void
- Unit省略するのが普通(だよね、知ってた)
fun printHoge(): Unit {
println("hoge")
}
fun printHoge() = println("hoge")