覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Kotlin - 中置呼び出し・分解宣言

Kotlin で マップを生成するために mapOf という関数を利用します。

例えば以下のように呼び出します。

val map = mapOf(1 to "1yen", 5 to "5yen", 10 to "10yen", 50 to "50yen")


この mapOf 関数の宣言は以下のようになされています

public fun <K, V> mapOf(vararg pairs: Pair<K, V>): Map<K, V>

Pair型 の 可変長引数を受け取る関数となっています。戻り値の関係性から キーと値のペアである必要があります。


mapOf を呼び出している引数から

1 to "1yen"

の部分が、Pair(1, "1yen") を作り出していることが分かります。


to というキーワードは組み込みの機能ではなく、メソッド呼び出し方法の特別な種類で 中置呼び出し(infix call)と呼ばれるものです。
中置呼び出しでは、メソッド名が対象オブジェクト名と引数の間に隣接して置かれます。余分なセパレータはありません。

以下2つの呼び出しは等価となります。

1.to("1yen")  // 普通の方法での to関数 の呼び出し
1 to "1yen"  // 中置記法を使った to関数 の呼び出し


といことなので冒頭の mapOf 関数でのマップ生成は以下のように書こうと思えば書けます

val map = mapOf(1.to("1yen"), 5.to("5yen"), 10.to("10yen"), 50.to("50yen"))


中置呼び出しは、1つの必須な引数を持つ通常のメソッドや拡張関数で使用可能です。
中置記法を使って関数を呼び出すためには、その関数に infix 修飾子を付ける必要があります。

ちなみに、to関数の宣言は以下のようになっています。

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

to関数は、Pairのインスンタスを返します。これは、Kotlinの標準ライブラリのクラスで要素のペアを表現しています。


Pair の中身を使って、以下のように二つの変数を直接初期化する事ができます。

val (num, yen) = 10 to "10yen"

この例では、num に 10 が yen に "10yen" が格納されます。

この機能を 分解宣言(destructuring declaration)と呼びます。


分解宣言は、ペアに対してだけ限定して利用されるものではなく、2つの変数keyとvalueをマップのエントリで初期化することにも利用できます。

例えば以下のようにループ内でマップのエントリをkeyとvalueで初期化しながら出力する事が可能です

val map = mapOf(1 to "1yen", 5 to "5yen", 10 to "10yen", 50 to "50yen")

for ((key, value) in map) {
    println("$key -> $value")
}

◾️実行結果

1 -> 1yen
5 -> 5yen
10 -> 10yen
50 -> 50yen


コレクションのループでwithIndex 関数を使う場合にも利用可能です

val list = listOf("1yen", "5yen", "10yne", "50yen", "100yne")

for ((index, element) in list.withIndex()) {
    println("list[$index] -> $element")
}

◾️実行結果

1 -> 1yen
5 -> 5yen
10 -> 10yen
50 -> 50yen