読者です 読者をやめる 読者になる 読者になる

算譜王におれはなる!!!!

偏りはあると思うけど情報技術全般についてマイペースに書くよ。

Kotlinの制御構文

Kotlin

※英語、または技術的な知識が至らず、内容に誤りが含まれるおそれがありますので、ご了承ください
※本エントリの8割は参考サイトの翻訳です。残りの2割は私の解釈で加筆や変更を施した構成です。

参考サイト http://confluence.jetbrains.net/display/Kotlin/Control+structures

if式

Kotlinにおいて if は式です!つまり値を返すのです。そのため三項演算子(条件 ? then : else)はありません(普通の if がその役割を担うからです)。

val a = 123
val message = if(a % 2 == 0 ) "偶数です" else "奇数です"

ifによる分岐は中括弧によってブロックを形成できます。最後の式がそのブロックの値となります。

val a = 123
val even : Boolean
  
val message = if(a % 2 == 0 ) {
  even = true
  "偶数です"
} else {
  even = false
  "奇数です"
} //messageには"奇数です"が代入される

ifが1つの分岐しか持たなかったり、分岐のうち1つでも結果がUnitの場合、そのif式の型はUnitとなります。

when式

whenはCライクな言語におけるswitch文に取って代わるものです。

when(gender) {
  'M' -> "Male"
  'F' -> "Female"
  else -> "Unknown"
}

whenは分岐条件が満たされるまで、すべての分岐に対して引数を比較していきます。whenは式で、合致した分岐の右側を返します。Unit型を返す分岐があると、そのwhen全体がUnit型となります。
複数のケースで同じ処理をしたいときには、カンマを打って分岐条件を結合させます。

when(n) {
  2, 3, 5, 7 -> println("$n is a prime number")
  1, 4, 6, 8, 9 -> println("$n is not a prime number")
  else -> println("Unknown")
}

分岐条件には定数だけでなく、任意の式を使うこともできます。

when(n) {
  1, 2, 3, 4, 5 -> println("1, 2, 3, 4, 5")
  foo(n) -> println("foo(n)")
  else -> println("Unknown")
}

ドットで始まる分岐条件は、真偽値として評価される関数やプロパティ(whenの引数上の)が呼び出され、その結果が trueなら分岐が実行されることを意味しています。

when(n) {
  .isFizz() -> println("Fizz")
  .isBuzz() -> println("Buzz")
}

次のようにレンジもチェックできます。

when(ch) {
  in 'a'..'z' -> println("小文字")
  in 'A'..'Z' -> println("大文字")
  else -> println("英字以外")
}

when式はパターンマッチングをサポートしています。次のコードを見てください*1

when (tuple) {
is (1, 2) -> ...
is (val a, 3) -> print(a) // binding a to the first element of the tuple
!is (*, 1100) -> ...
}

※マッチする分岐条件が存在しない場合、whenは例外を投げます

when内でのcontinue

when内のcontinueは、次の分岐条件にジャンプする機能を持ちます*2。最後の分岐での(つまり次の分岐条件がないとき)continueはエラーとなります。

forループ

forループはイテレータを提供するものなら何でも繰り返します。

fun main(args : Array<String>) {
  for(arg in args)
    println(arg)
}

ループ変数に型や val, varを指定することもできます。ボディのブロック化もできます。

for(val arg : String in args) {
  println(arg)
}

前述の「イテレータを提供するもの」とは次のようなオブジェクトです。

  1. iterator()というインスタンス関数(または拡張関数)を持っている
  2. next()というインスタンス関数(または拡張関数)を持っている
  3. 「hasNextというBoolean型のプロパティ」または「hasNext()というBoolean型を返す関数」を持っている

配列やリストを、添字を使って繰り返したい場合は次のように書きます。

for(i in args.indices) {
  println(args[i])
}

※レンジの繰り返しでは、余分なオブジェクトが生成されないように最適化されるらしいですよ…!

whileとdo whileループ

基本的にJavaと同じです。

do {
  val a = hoge()
} while(a > 0)

Javaと違うところは、上記コードのように、do内で宣言した変数にwhileの条件のところから「見える」ところです*3

breakやcontinueについて詳しいお話はまた今度。

*1:http://confluence.jetbrains.net/display/Kotlin/Control+structuresより引用

*2:[http://kotlin-demo.jetbrains.com/:title]で試すとエラーとなってしまいます。「'break' and 'continue' are only allowed inside a loop」というエラーメッセージが吐かれるので、仕様が変わったのかな?

*3:Kotlinのバグトラッカにissue登録したところ、修正され、ビルド0.1.280で反映されるそうです