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.mapAll
|
||||||
import com.github.michaelbull.result.mapBoth
|
import com.github.michaelbull.result.mapBoth
|
||||||
import com.github.michaelbull.result.mapError
|
import com.github.michaelbull.result.mapError
|
||||||
|
import com.github.michaelbull.result.runCatching
|
||||||
import com.github.michaelbull.result.toResultOr
|
import com.github.michaelbull.result.toResultOr
|
||||||
import java.sql.SQLTimeoutException
|
import java.sql.SQLTimeoutException
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ object CustomerService {
|
|||||||
private val repository = InMemoryCustomerRepository()
|
private val repository = InMemoryCustomerRepository()
|
||||||
|
|
||||||
fun getAll(): Result<Collection<Customer>, DomainMessage> {
|
fun getAll(): Result<Collection<Customer>, DomainMessage> {
|
||||||
return Result.of(repository::findAll)
|
return runCatching(repository::findAll)
|
||||||
.mapError(::exceptionToDomainMessage)
|
.mapError(::exceptionToDomainMessage)
|
||||||
.mapAll(Customer.Companion::from)
|
.mapAll(Customer.Companion::from)
|
||||||
}
|
}
|
||||||
@ -40,12 +41,12 @@ object CustomerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCustomer(entity: CustomerEntity, old: Customer, new: Customer) =
|
private fun updateCustomer(entity: CustomerEntity, old: Customer, new: Customer) =
|
||||||
Result.of { repository.update(entity) }
|
runCatching { repository.update(entity) }
|
||||||
.map { differenceBetween(old, new) }
|
.map { differenceBetween(old, new) }
|
||||||
.mapError(::exceptionToDomainMessage)
|
.mapError(::exceptionToDomainMessage)
|
||||||
|
|
||||||
private fun createCustomer(entity: CustomerEntity) =
|
private fun createCustomer(entity: CustomerEntity) =
|
||||||
Result.of { repository.insert(entity) }
|
runCatching { repository.insert(entity) }
|
||||||
.map { CustomerCreated }
|
.map { CustomerCreated }
|
||||||
.mapError(::exceptionToDomainMessage)
|
.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
|
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]).
|
* [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]
|
* Invokes a [function] and wraps it in a [Result], returning an [Err]
|
||||||
* if an [Exception] was thrown, otherwise [Ok].
|
* 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> {
|
inline fun <V> of(function: () -> V): Result<V, Exception> {
|
||||||
return try {
|
return try {
|
||||||
Ok(function.invoke())
|
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].
|
* Represents a failed [Result], containing an [error].
|
||||||
*/
|
*/
|
||||||
data class Err<out E>(val error: E) : Result<Nothing, E>()
|
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.assertEquals
|
||||||
import kotlin.test.assertSame
|
import kotlin.test.assertSame
|
||||||
|
|
||||||
class ResultTest {
|
class FactoryTest {
|
||||||
class Of {
|
class RunCatching {
|
||||||
@Test
|
@Test
|
||||||
fun returnsOkIfInvocationSuccessful() {
|
fun returnsOkIfInvocationSuccessful() {
|
||||||
val callback = { "example" }
|
val callback = { "example" }
|
||||||
val result = Result.of(callback)
|
val result = runCatching(callback)
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = "example",
|
expected = "example",
|
||||||
@ -21,7 +21,7 @@ class ResultTest {
|
|||||||
fun returnsErrIfInvocationFails() {
|
fun returnsErrIfInvocationFails() {
|
||||||
val exception = IllegalArgumentException("throw me")
|
val exception = IllegalArgumentException("throw me")
|
||||||
val callback = { throw exception }
|
val callback = { throw exception }
|
||||||
val result = Result.of(callback)
|
val result = runCatching(callback)
|
||||||
|
|
||||||
assertSame(
|
assertSame(
|
||||||
expected = exception,
|
expected = exception,
|
Loading…
Reference in New Issue
Block a user