【Kotlin】Boolean のソート

[`Boolean` クラス](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/)は、[`Comparable` インターフェイス](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-comparable/)を実装しているため、
大小比較をすることができます。
`true` と `false` のどちらが大きいかは、API ドキュメントや言語仕様書にも記載されていないようですが、
`false < true` です（Java の [`Boolean` クラス](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Boolean.html#compareTo(java.lang.Boolean))と同じです。Java の API ドキュメントには記載されています）。

そのため `Boolean` 値のコレクションをソートすると
`false` が前（インデックスが小さい方）
`true` が後ろ（インデックスが大きい方）
に来ます。

```Kotlin
listOf(true, false, true, false)
    .sorted()
    .also { println(it) } // > [false, false, true, true]
```

ただしこれは直観的とは言いがたいので、
少なくともコメントを付けておいた方がよいでしょう。

```Kotlin
listOf(true, false, true, false)
    .sorted() // false が前（インデックスが小さい方）に来る
    .also { println(it) } // > [false, false, true, true]
```

## コメントなしでも直感的に分かるようにする

次のような、`Comparator<Boolean>` オブジェクトを返す関数[^関数名]を用意しておいて

[^関数名]: 関数名は [`nullsFirst`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.comparisons/nulls-first.html), [`nullsLast`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.comparisons/nulls-last.html) に倣いました。


```Kotlin
/** `false < true` であるとする [Comparator] を返す。 */
fun falsesFirst(): Comparator<Boolean> = compareBy { it }

/** `true < false` であるとする [Comparator] を返す。 */
fun falsesLast(): Comparator<Boolean> = compareByDescending { it }

/** `true < false` であるとする [Comparator] を返す。 */
fun truesFirst(): Comparator<Boolean> = compareByDescending { it }

/** `false < true` であるとする [Comparator] を返す。 */
fun truesLast(): Comparator<Boolean> = compareBy { it }
```

次のように使えば、
コメントを付けなくても直観的に分かるようにできます。

```Kotlin
listOf(true, false, true, false)
    .sortedWith(falsesFirst())
    .also { println(it) } // > [false, false, true, true]

listOf(true, false, true, false)
    .sortedWith(falsesLast())
    .also { println(it) } // > [true, true, false, false]

listOf(true, false, true, false)
    .sortedWith(truesFirst())
    .also { println(it) } // > [true, true, false, false]

listOf(true, false, true, false)
    .sortedWith(truesLast())
    .also { println(it) } // > [false, false, true, true]
```

## 現実的な使い方

実際には、`Boolean` そのもののコレクションをソートすることはまずなく、
各要素のプロパティなどから計算した `Boolean` 型の値に応じてソートすることになるでしょう。
その場合は例えば次のようになります。

```Kotlin
data class MyClass(
    val value: Boolean
)


listOf(MyClass(true), MyClass(false), MyClass(true), MyClass(false))
    .sortedWith(
        compareBy(falsesFirst()) { it.value }
    )
    .also { println(it) } // > [MyClass(value=false), MyClass(value=false), MyClass(value=true), MyClass(value=true)]

listOf(MyClass(true), MyClass(false), MyClass(true), MyClass(false))
    .sortedWith(
        compareBy(falsesLast()) { it.value }
    )
    .also { println(it) } // > [MyClass(value=true), MyClass(value=true), MyClass(value=false), MyClass(value=false)]

listOf(MyClass(true), MyClass(false), MyClass(true), MyClass(false))
    .sortedWith(
        compareBy(truesFirst()) { it.value }
    )
    .also { println(it) } // > [MyClass(value=true), MyClass(value=true), MyClass(value=false), MyClass(value=false)]

listOf(MyClass(true), MyClass(false), MyClass(true), MyClass(false))
    .sortedWith(
        compareBy(truesLast()) { it.value }
    )
    .also { println(it) } // > [MyClass(value=false), MyClass(value=false), MyClass(value=true), MyClass(value=true)]
```

／以上