Add mapping function for transformations with ResultsWithDiagnostics

also improve chaining helpers
This commit is contained in:
Ilya Chernikov
2019-01-08 12:18:39 +01:00
parent 01f2a21192
commit 7bb4233e17
@@ -60,18 +60,41 @@ sealed class ResultWithDiagnostics<out R> {
* If receiver is success - executes [body] and merge diagnostic reports * If receiver is success - executes [body] and merge diagnostic reports
* otherwise returns the failure as is * otherwise returns the failure as is
*/ */
suspend fun <R1, R2> ResultWithDiagnostics<R1>.onSuccess(body: suspend (R1) -> ResultWithDiagnostics<R2>): ResultWithDiagnostics<R2> = inline fun <R1, R2> ResultWithDiagnostics<R1>.onSuccess(body: (R1) -> ResultWithDiagnostics<R2>): ResultWithDiagnostics<R2> =
when (this) { when (this) {
is ResultWithDiagnostics.Success -> this.reports + body(this.value) is ResultWithDiagnostics.Success -> this.reports + body(this.value)
is ResultWithDiagnostics.Failure -> this is ResultWithDiagnostics.Failure -> this
} }
/**
* maps transformation ([body]) over iterable merging diagnostics
* return failure with merged diagnostics after first failed transformation
* and success with merged diagnostics and list of results if all transformations succeeded
*/
inline fun<T, R> Iterable<T>.mapSuccess(body: (T) -> ResultWithDiagnostics<R>): ResultWithDiagnostics<List<R>> {
val reports = ArrayList<ScriptDiagnostic>()
val results = ArrayList<R>()
for (it in this) {
val result = body(it)
reports.addAll(result.reports)
when (result) {
is ResultWithDiagnostics.Success -> {
results.add(result.value)
}
else -> {
return ResultWithDiagnostics.Failure(reports)
}
}
}
return results.asSuccess(reports)
}
/** /**
* Chains actions on failure: * Chains actions on failure:
* If receiver is failure - executed [body] * If receiver is failure - executed [body]
* otherwise returns the receiver as is * otherwise returns the receiver as is
*/ */
suspend fun <R> ResultWithDiagnostics<R>.onFailure(body: suspend (ResultWithDiagnostics<R>) -> Unit): ResultWithDiagnostics<R> { inline fun <R> ResultWithDiagnostics<R>.onFailure(body: (ResultWithDiagnostics<R>) -> Unit): ResultWithDiagnostics<R> {
if (this is ResultWithDiagnostics.Failure) { if (this is ResultWithDiagnostics.Failure) {
body(this) body(this)
} }