Deprecate "ResultBinding" in favour of "BindingScope"

This matches the Kotlin stdlib naming convention used for
sequences[1] and coroutines[2].

[1] https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.sequences/-sequence-scope/
[2] https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/
This commit is contained in:
Michael Bull 2024-03-10 23:32:17 +00:00
parent 09818a7d50
commit dd5c96f983
3 changed files with 30 additions and 18 deletions

View File

@ -20,16 +20,16 @@ import kotlin.coroutines.CoroutineContext
* This new scope is [cancelled][CoroutineScope.cancel] once a failing bind is encountered, eagerly cancelling all
* child [jobs][Job].
*/
public suspend inline fun <V, E> binding(crossinline block: suspend SuspendableResultBinding<E>.() -> V): Result<V, E> {
public suspend inline fun <V, E> binding(crossinline block: suspend CoroutineBindingScope<E>.() -> V): Result<V, E> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
lateinit var receiver: SuspendableResultBindingImpl<E>
lateinit var receiver: CoroutineBindingScopeImpl<E>
return try {
coroutineScope {
receiver = SuspendableResultBindingImpl(this)
receiver = CoroutineBindingScopeImpl(this)
with(receiver) {
Ok(block())
@ -42,14 +42,20 @@ public suspend inline fun <V, E> binding(crossinline block: suspend SuspendableR
internal object BindCancellationException : CancellationException(null as String?)
public interface SuspendableResultBinding<E> : CoroutineScope {
@Deprecated(
message = "Use CoroutineBindingScope instead",
replaceWith = ReplaceWith("CoroutineBindingScope<E>")
)
public typealias SuspendableResultBinding<E> = CoroutineBindingScope<E>
public interface CoroutineBindingScope<E> : CoroutineScope {
public suspend fun <V> Result<V, E>.bind(): V
}
@PublishedApi
internal class SuspendableResultBindingImpl<E>(
internal class CoroutineBindingScopeImpl<E>(
delegate: CoroutineScope,
) : SuspendableResultBinding<E>, CoroutineScope by delegate {
) : CoroutineBindingScope<E>, CoroutineScope by delegate {
private val mutex = Mutex()
var result: Result<Nothing, E>? = null

View File

@ -4,10 +4,10 @@ import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
/**
* Calls the specified function [block] with [ResultBinding] as its receiver and returns its [Result].
* Calls the specified function [block] with [BindingScope] as its receiver and returns its [Result].
*
* When inside a [binding] block, the [bind][ResultBinding.bind] function is accessible on any [Result]. Calling the
* [bind][ResultBinding.bind] function will attempt to unwrap the [Result] and locally return its [value][Ok.value]. If
* When inside a [binding] block, the [bind][BindingScope.bind] function is accessible on any [Result]. Calling the
* [bind][BindingScope.bind] function will attempt to unwrap the [Result] and locally return its [value][Ok.value]. If
* the [Result] is an [Err], the binding block will terminate with that bind and return that failed-to-bind [Err].
*
* Example:
@ -22,12 +22,12 @@ import kotlin.contracts.contract
* }
* ```
*/
public inline fun <V, E> binding(crossinline block: ResultBinding<E>.() -> V): Result<V, E> {
public inline fun <V, E> binding(crossinline block: BindingScope<E>.() -> V): Result<V, E> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return with(ResultBindingImpl<E>()) {
return with(BindingScopeImpl<E>()) {
try {
Ok(block())
} catch (ex: BindException) {
@ -38,12 +38,18 @@ public inline fun <V, E> binding(crossinline block: ResultBinding<E>.() -> V): R
internal expect object BindException : Exception
public interface ResultBinding<E> {
@Deprecated(
message = "Use BindingScope instead",
replaceWith = ReplaceWith("BindingScope<E>")
)
public typealias ResultBinding<E> = BindingScope<E>
public interface BindingScope<E> {
public fun <V> Result<V, E>.bind(): V
}
@PublishedApi
internal class ResultBindingImpl<E> : ResultBinding<E> {
internal class BindingScopeImpl<E> : BindingScope<E> {
var result: Result<Nothing, E>? = null
@ -51,7 +57,7 @@ internal class ResultBindingImpl<E> : ResultBinding<E> {
return when (this) {
is Ok -> value
is Err -> {
this@ResultBindingImpl.result = this
this@BindingScopeImpl.result = this
throw BindException
}
}

View File

@ -1,10 +1,10 @@
package com.github.michaelbull.result.coroutines
import com.github.michaelbull.result.BindException
import com.github.michaelbull.result.BindingScope
import com.github.michaelbull.result.BindingScopeImpl
import com.github.michaelbull.result.Ok
import com.github.michaelbull.result.Result
import com.github.michaelbull.result.ResultBinding
import com.github.michaelbull.result.ResultBindingImpl
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
@ -17,12 +17,12 @@ import kotlin.contracts.contract
"Please import the kotlin-result-coroutines library to continue using this feature.",
level = DeprecationLevel.WARNING
)
public suspend inline fun <V, E> binding(crossinline block: suspend ResultBinding<E>.() -> V): Result<V, E> {
public suspend inline fun <V, E> binding(crossinline block: suspend BindingScope<E>.() -> V): Result<V, E> {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return with(ResultBindingImpl<E>()) {
return with(BindingScopeImpl<E>()) {
try {
Ok(block())
} catch (ex: BindException) {