Emil Kantis
09/07/2021, 9:30 PMtrySingle
for collections) would be useful as part of the stdlib? Or have any alternate solutions? 🙂
fun doSomething(customerId: Int) {
val user = when (val result = fetchExistingUsers().trySingle { it.id == customerId }) {
is MultipleFound -> error("Duplicate users for single ID")
is NoneFound -> createUser()
is Single -> result.single
}
}
Emil Kantis
09/07/2021, 9:32 PMtrySingle
is a slightly modified singleOrNull
sealed interface TrySingleResult<out T>
class Single<T>(
val single: T
) : TrySingleResult<T>
object MultipleFound: TrySingleResult<Nothing>
object NoneFound: TrySingleResult<Nothing>
inline fun <T> Iterable<T>.trySingle(predicate: (T) -> Boolean): TrySingleResult<T> {
var single: T? = null
var found = false
for (element in this) {
if (predicate(element)) {
if (found) return MultipleFound
single = element
found = true
}
}
if (!found) return NoneFound
@Suppress("UNCHECKED_CAST")
return Single(single as T)
}
ephemient
09/07/2021, 9:57 PMfetchExistingUsers().filter { _.id == customerId } match {
List(singleId) => singleId
List(_, _*) => error(...)
_ => error(...)
}
there isn't a finished design for what it would look like in Kotlin, but https://youtrack.jetbrains.com/issue/KT-186 may be coming in a future version of Kotlinhfhbd
09/07/2021, 10:10 PMfilter
and check its size.Emil Kantis
09/07/2021, 10:14 PMwhen
-clause forces you to deal with all branches immediately (multiple, single and none). I think it's generally preferableephemient
09/07/2021, 10:15 PMwhen (result.size) { 0 -> ; 1 -> ; _ -> }
ephemient
09/07/2021, 10:15 PMhfhbd
09/07/2021, 10:19 PMfun doSomething(customerId: Int) {
val user = fetchExistingUsers().filter { it.id == customerId }.let {
when(it.size) {
0 -> createUser()
1 -> it.single()
else -> error("Duplicate users for single ID")
}
}
Emil Kantis
09/07/2021, 10:23 PMtrySingle(predicate: (T) -> Boolean): Result<T?>
using Kotlin's built-in Result
-type.. Then you can do something like:
fun doSomething(customerId: Int) {
val user = fetchExistingUsers()
.trySingle { it.id == customerId }
.getOrElse { println("Multiple found") }
?: createUser()
}
Emil Kantis
09/07/2021, 10:25 PMwhen
🙂