littlelightcz
10/11/2018, 7:10 PMList<Result<T>>
(when using runCatching {}
) which would help be execute some action in case there have been some failures etc.? Since I think this is (or will be) a very common design pattern - similarly as there is a convenience ext. function for List<Deferred<T>>.awaitAll()
.
Recently I was thinking it could be done in the similar fashion as the current .onFailure()
and .onSuccess()
except that the lambda would take List<Throwable>
or List<T>
as an argument (respectively).
Currently what I need to do on such list, is: (1) filter { it.isFailure}
, then (2) I need to check that it is not empty, and not until now (3) I can do something with it. With the above proposal the first 2 steps would be unnecessary and I would be able to define just the part which would execute only if there was at least 1 failed Result. Similarly it could work for successful Result values.gildor
10/12/2018, 1:05 AMmapNonNull { it.getOrNull() }
gildor
10/12/2018, 1:07 AMmap { it.getOrThrow() }
gildor
10/12/2018, 1:09 AMlittlelightcz
10/12/2018, 4:40 PMval results = (1..5).map {
runCatching {
if (it % 2 == 0) throw Exception("Oops!") else it
}
}
val failed = results.filter { it.isFailure }
if (failed.isNotEmpty()) {
println("There were ${failed.size} failures and the first one was: ${failed.first().exceptionOrNull()}")
}
println("Succeeded were:")
results.filter { it.isSuccess }.forEach { println(it.getOrNull()) }
Wouldn't it be much better if I could write it e.g. like this?
(1..5).map {
runCatching {
if (it % 2 == 0) throw Exception("Oops!") else it
}
}
.onFailed { println("There were ${it.size} failures and the first one was: ${it.first()}") }
.onSucceeded { succeeded ->
println("Succeeded were:")
succeeded.forEach { println(it) }
}
gildor
10/13/2018, 3:29 AMgildor
10/13/2018, 3:29 AMgroupBy
gildor
10/13/2018, 3:31 AMgildor
10/13/2018, 3:32 AMgildor
10/13/2018, 3:35 AMval succeed = (1..5).mapNonNull {
if (it % 2 == 0) {
println("Failure of operation $it")
null
} else {
it
}
}
}
println("Succeeded were:")
succeed.forEach { println(it) }
gildor
10/13/2018, 3:35 AMgildor
10/13/2018, 3:36 AMlittlelightcz
10/23/2018, 5:41 PM.onFailed { }
as I was thinking about it cannot be used. So I am still with your mapNotNull
solution (it saves one filter
call 😁), so thanks so far 🙂dave08
11/01/2018, 7:20 AMval (successful, failed) = results.partition { it.isSuccess }
, instead of two filters...littlelightcz
11/01/2018, 7:00 PMPair<List<Result<T>>, List<Result<T>>>
. If it gave me Pair<List<T>, List<Throwable>>
then I would be good with it 😁.dave08
11/02/2018, 8:46 AMlittlelightcz
11/02/2018, 6:11 PMinline fun <T: Any> Collection<Result<T>>.partitionByResult() = mapNotNull { it.getOrNull() } to mapNotNull { it.exceptionOrNull() }
Then having this example:
fun main() {
val results = listOf(
runCatching { "Hi" },
runCatching { throw Exception("Oops") }
)
val (ok, errors) = results.partitionByResult()
println(ok)
println(errors)
}
The output is:
[Hi]
[java.lang.Exception: Oops]
ilya.gorbunov
11/02/2018, 9:22 PMpartitionBySuccess
. Could you open an issue for this proposal?littlelightcz
11/03/2018, 6:36 PM