Wrapper for kotlin.Result with KMM goodness, s.t. it becomes possible to expose a result class to
public APIs interfacing with platform-specific code. For Kotlin/Native (read: iOS), this requires a Result equivalent, which
is not a value class (a sealed Either type also does not interop well with Swift).
KmmResult comes to the rescue on all KMP targets! → Full documentation.
This library is available at maven central.
dependencies {
api("at.asitplus:kmmresult:$version") //This library was designed to play well with multiplatform APIs
} //and is therefore intended to be exposed through your public APICreation of Success and Failure objects is provided through a companion:
var intResult = KmmResult.success(3)
intResult = KmmResult.failure (NotImplementedError("Not Implemented"))Convenience functions:
map()transforms success types while passing through errorstransform()transforms aKmmResultof one type to another, leaving failure-cases untouched and preventing nestedKmmResults.mapFailuretransforms error types while passing through success cases- the more generic
fold()is available for conveniently operating on both success and failure branches KmmResultsportsunwrap()to conveniently map it to thekotlin.ResultequivalentResult.wrap()extension function goes the opposite waymapCatching()does what you'd expectwrapping()allows for wrapping the failure branch's exception unless it is of the specified typeonSuccess()andonFailure()transforming success and error cases, respectively.
Refer to the full documentation for more info.
Works from the JVM as expected:
KmmResult<Boolean> demonstrate() {
if (new Random().nextBoolean())
return KmmResult.failure(new NotImplementedError("Not Implemented"));
else
return KmmResult.success(true);
}Use the initializers:
func funWithKotlin() -> KmmResult<NSString> {
if 2 != 3 {
return KmmResult(failure: KotlinThrowable(message: "error!"))
} else {
return KmmResult(value: "works!")
}
}The kmmresult-test artefact provides first-class Kotest integration:
catching {…} should suceedcatching {…} shouldSucceedWith someSuccessValuecatching {…}.shouldSucceed()returns the value of the success case. Causes a failed assertion otherwise.
KmmResult comes with catching. This is a non-fatal-only-catching version of stdlib's runCatching, directly returning a KmmResult.
It re-throws any fatal exceptions, such as OutOfMemoryError. The underlying logic is borrowed from Arrow's's
nonFatalOrThrow.
The only downside of catching is that it incurs instantiation overhead, because it creates a KmmResult instance.
Internally, though, only the behaviour is important, not Swift interop. Hence, you don't care for a KmmResult and you
certainly don't care for the cost of instantiating an object. Here, the Result.nonFatalOrThrow() extension shipped with KmmResult
comes to the rescue. It does exactly what the name suggest: It re-throws any fatal exception and leaves the Result object
untouched otherwise. As a convenience shorthand, there's catchingUnwrapped which directly returns an stdlib Result.
Happy folding!
External contributions are greatly appreciated! Just be sure to observe the contribution guidelines (see CONTRIBUTING.md).
The Apache License does not apply to the logos, (including the A-SIT logo) and the project/module name(s), as these are the sole property of A-SIT/A-SIT Plus GmbH and may not be used in derivative works without explicit permission!
