Deprecate Result.of in favour of runCatching factory function
Matches Kotlin's stdlib and becomes top-level
This commit is contained in:
parent
a8098db1c7
commit
586b260683
@ -15,6 +15,7 @@ import com.github.michaelbull.result.map
|
||||
import com.github.michaelbull.result.mapAll
|
||||
import com.github.michaelbull.result.mapBoth
|
||||
import com.github.michaelbull.result.mapError
|
||||
import com.github.michaelbull.result.runCatching
|
||||
import com.github.michaelbull.result.toResultOr
|
||||
import java.sql.SQLTimeoutException
|
||||
|
||||
@ -22,7 +23,7 @@ object CustomerService {
|
||||
private val repository = InMemoryCustomerRepository()
|
||||
|
||||
fun getAll(): Result<Collection<Customer>, DomainMessage> {
|
||||
return Result.of(repository::findAll)
|
||||
return runCatching(repository::findAll)
|
||||
.mapError(::exceptionToDomainMessage)
|
||||
.mapAll(Customer.Companion::from)
|
||||
}
|
||||
@ -40,12 +41,12 @@ object CustomerService {
|
||||
}
|
||||
|
||||
private fun updateCustomer(entity: CustomerEntity, old: Customer, new: Customer) =
|
||||
Result.of { repository.update(entity) }
|
||||
runCatching { repository.update(entity) }
|
||||
.map { differenceBetween(old, new) }
|
||||
.mapError(::exceptionToDomainMessage)
|
||||
|
||||
private fun createCustomer(entity: CustomerEntity) =
|
||||
Result.of { repository.insert(entity) }
|
||||
runCatching { repository.insert(entity) }
|
||||
.map { CustomerCreated }
|
||||
.mapError(::exceptionToDomainMessage)
|
||||
|
||||
|
53
src/main/kotlin/com/github/michaelbull/result/Factory.kt
Normal file
53
src/main/kotlin/com/github/michaelbull/result/Factory.kt
Normal file
@ -0,0 +1,53 @@
|
||||
package com.github.michaelbull.result
|
||||
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Calls the specified function [block] and returns its encapsulated result if
|
||||
* invocation was successful, catching and encapsulating any thrown exception
|
||||
* as a failure.
|
||||
*/
|
||||
inline fun <V> runCatching(block: () -> V): Result<V, Throwable> {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
return try {
|
||||
Ok(block())
|
||||
} catch (e: Throwable) {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified function [block] with `this` value as its receiver and
|
||||
* returns its encapsulated result if invocation was successful, catching and
|
||||
* encapsulating any thrown exception as a failure.
|
||||
*/
|
||||
inline infix fun <T, V> T.runCatching(block: T.() -> V): Result<V, Throwable> {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
return try {
|
||||
Ok(block())
|
||||
} catch (e: Throwable) {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a nullable of type [V] to a [Result]. Returns [Ok] if the value is
|
||||
* non-null, otherwise the supplied [error].
|
||||
*/
|
||||
inline infix fun <V, E> V?.toResultOr(error: () -> E): Result<V, E> {
|
||||
contract {
|
||||
callsInPlace(error, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
null -> Err(error())
|
||||
else -> Ok(this)
|
||||
}
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
package com.github.michaelbull.result
|
||||
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* [Result] is a type that represents either success ([Ok]) or failure ([Err]).
|
||||
*
|
||||
@ -17,6 +14,7 @@ sealed class Result<out V, out E> {
|
||||
* Invokes a [function] and wraps it in a [Result], returning an [Err]
|
||||
* if an [Exception] was thrown, otherwise [Ok].
|
||||
*/
|
||||
@Deprecated("Use top-level runCatching instead", ReplaceWith("runCatching(function)"))
|
||||
inline fun <V> of(function: () -> V): Result<V, Exception> {
|
||||
return try {
|
||||
Ok(function.invoke())
|
||||
@ -36,18 +34,3 @@ data class Ok<out V>(val value: V) : Result<V, Nothing>()
|
||||
* Represents a failed [Result], containing an [error].
|
||||
*/
|
||||
data class Err<out E>(val error: E) : Result<Nothing, E>()
|
||||
|
||||
/**
|
||||
* Converts a nullable of type [V] to a [Result]. Returns [Ok] if the value is
|
||||
* non-null, otherwise the supplied [error].
|
||||
*/
|
||||
inline infix fun <V, E> V?.toResultOr(error: () -> E): Result<V, E> {
|
||||
contract {
|
||||
callsInPlace(error, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
|
||||
return when (this) {
|
||||
null -> Err(error())
|
||||
else -> Ok(this)
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,12 @@ import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertSame
|
||||
|
||||
class ResultTest {
|
||||
class Of {
|
||||
class FactoryTest {
|
||||
class RunCatching {
|
||||
@Test
|
||||
fun returnsOkIfInvocationSuccessful() {
|
||||
val callback = { "example" }
|
||||
val result = Result.of(callback)
|
||||
val result = runCatching(callback)
|
||||
|
||||
assertEquals(
|
||||
expected = "example",
|
||||
@ -21,7 +21,7 @@ class ResultTest {
|
||||
fun returnsErrIfInvocationFails() {
|
||||
val exception = IllegalArgumentException("throw me")
|
||||
val callback = { throw exception }
|
||||
val result = Result.of(callback)
|
||||
val result = runCatching(callback)
|
||||
|
||||
assertSame(
|
||||
expected = exception,
|
Loading…
Reference in New Issue
Block a user