Skip to content

Commit 14f94f7

Browse files
authored
Add catch with transform (#3751)
1 parent 5c8435c commit 14f94f7

File tree

5 files changed

+44
-2
lines changed

5 files changed

+44
-2
lines changed

arrow-libs/core/arrow-core/api/android/arrow-core.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,7 @@ public final class arrow/core/raise/RaiseKt {
10431043
public static final fun _foldOrThrow (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
10441044
public static final fun _merge (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
10451045
public static final fun catch (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
1046+
public static final fun catch (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
10461047
public static final fun catch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function1;
10471048
public static final fun catch (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2;
10481049
public static final fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function2;

arrow-libs/core/arrow-core/api/arrow-core.klib.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,7 @@ final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin/Result<#A>).arrow.co
10161016
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core.raise.context/either(kotlin/Function1<arrow.core.raise/Raise<#A>, #B>): arrow.core/Either<#A, #B> // arrow.core.raise.context/either|either(kotlin.Function1<arrow.core.raise.Raise<0:0>,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
10171017
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core.raise.context/ior(noinline kotlin/Function2<#A, #A, #A>, kotlin/Function1<arrow.core.raise/IorRaise<#A>, #B>): arrow.core/Ior<#A, #B> // arrow.core.raise.context/ior|ior(kotlin.Function2<0:0,0:0,0:0>;kotlin.Function1<arrow.core.raise.IorRaise<0:0>,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
10181018
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core.raise.context/iorNel(noinline kotlin/Function2<arrow.core/NonEmptyList<#A>, arrow.core/NonEmptyList<#A>, arrow.core/NonEmptyList<#A>> = ..., kotlin/Function1<arrow.core.raise/IorRaise<arrow.core/NonEmptyList<#A>>, #B>): arrow.core/Ior<arrow.core/NonEmptyList<#A>, #B> // arrow.core.raise.context/iorNel|iorNel(kotlin.Function2<arrow.core.NonEmptyList<0:0>,arrow.core.NonEmptyList<0:0>,arrow.core.NonEmptyList<0:0>>;kotlin.Function1<arrow.core.raise.IorRaise<arrow.core.NonEmptyList<0:0>>,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
1019+
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core.raise/catch(kotlin/Function0<#A>, kotlin/Function1<#A, #B>, kotlin/Function1<kotlin/Throwable, #B>): #B // arrow.core.raise/catch|catch(kotlin.Function0<0:0>;kotlin.Function1<0:0,0:1>;kotlin.Function1<kotlin.Throwable,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
10191020
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core.raise/eagerEffect(noinline kotlin/Function1<arrow.core.raise/Raise<#A>, #B>): kotlin/Function1<arrow.core.raise/Raise<#A>, #B> // arrow.core.raise/eagerEffect|eagerEffect(kotlin.Function1<arrow.core.raise.Raise<0:0>,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
10201021
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core.raise/effect(noinline kotlin.coroutines/SuspendFunction1<arrow.core.raise/Raise<#A>, #B>): kotlin.coroutines/SuspendFunction1<arrow.core.raise/Raise<#A>, #B> // arrow.core.raise/effect|effect(kotlin.coroutines.SuspendFunction1<arrow.core.raise.Raise<0:0>,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
10211022
final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core.raise/either(kotlin/Function1<arrow.core.raise/Raise<#A>, #B>): arrow.core/Either<#A, #B> // arrow.core.raise/either|either(kotlin.Function1<arrow.core.raise.Raise<0:0>,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
@@ -1054,6 +1055,7 @@ final inline fun <#A: kotlin/Comparable<#A>> (arrow.core/NonEmptyList<#A>).arrow
10541055
final inline fun <#A: reified kotlin/Any?> (arrow.core/Option<*>).arrow.core/filterIsInstance(): arrow.core/Option<#A> // arrow.core/filterIsInstance|filterIsInstance@arrow.core.Option<*>(){0§<kotlin.Any?>}[0]
10551056
final inline fun <#A: reified kotlin/Throwable, #B: kotlin/Any?, #C: kotlin/Any?> (kotlin.coroutines/SuspendFunction1<arrow.core.raise/Raise<#B>, #C>).arrow.core.raise/catch(crossinline kotlin.coroutines/SuspendFunction2<arrow.core.raise/Raise<#B>, #A, #C>): kotlin.coroutines/SuspendFunction1<arrow.core.raise/Raise<#B>, #C> // arrow.core.raise/catch|catch@kotlin.coroutines.SuspendFunction1<arrow.core.raise.Raise<0:1>,0:2>(kotlin.coroutines.SuspendFunction2<arrow.core.raise.Raise<0:1>,0:0,0:2>){0§<kotlin.Throwable>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
10561057
final inline fun <#A: reified kotlin/Throwable, #B: kotlin/Any?, #C: kotlin/Any?> (kotlin/Function1<arrow.core.raise/Raise<#B>, #C>).arrow.core.raise/catch(crossinline kotlin/Function2<arrow.core.raise/Raise<#B>, #A, #C>): kotlin/Function1<arrow.core.raise/Raise<#B>, #C> // arrow.core.raise/catch|catch@kotlin.Function1<arrow.core.raise.Raise<0:1>,0:2>(kotlin.Function2<arrow.core.raise.Raise<0:1>,0:0,0:2>){0§<kotlin.Throwable>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
1058+
final inline fun <#A: reified kotlin/Throwable, #B: kotlin/Any?, #C: kotlin/Any?> arrow.core.raise/catch(kotlin/Function0<#B>, kotlin/Function1<#B, #C>, kotlin/Function1<#A, #C>): #C // arrow.core.raise/catch|catch(kotlin.Function0<0:1>;kotlin.Function1<0:1,0:2>;kotlin.Function1<0:0,0:2>){0§<kotlin.Throwable>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
10571059
final inline fun <#A: reified kotlin/Throwable, #B: kotlin/Any?, #C: kotlin/Any?> arrow.core.raise/recover(kotlin/Function1<arrow.core.raise/Raise<#B>, #C>, kotlin/Function1<#B, #C>, kotlin/Function1<#A, #C>): #C // arrow.core.raise/recover|recover(kotlin.Function1<arrow.core.raise.Raise<0:1>,0:2>;kotlin.Function1<0:1,0:2>;kotlin.Function1<0:0,0:2>){0§<kotlin.Throwable>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
10581060
final inline fun <#A: reified kotlin/Throwable, #B: kotlin/Any?> arrow.core.raise/catch(kotlin/Function0<#B>, kotlin/Function1<#A, #B>): #B // arrow.core.raise/catch|catch(kotlin.Function0<0:1>;kotlin.Function1<0:0,0:1>){0§<kotlin.Throwable>;1§<kotlin.Any?>}[0]
10591061
final inline fun arrow.core.raise.context/impure(kotlin/Function1<arrow.core.raise/SingletonRaise<kotlin/Unit>, kotlin/Unit>) // arrow.core.raise.context/impure|impure(kotlin.Function1<arrow.core.raise.SingletonRaise<kotlin.Unit>,kotlin.Unit>){}[0]

arrow-libs/core/arrow-core/api/jvm/arrow-core.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,7 @@ public final class arrow/core/raise/RaiseKt {
10431043
public static final fun _foldOrThrow (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
10441044
public static final fun _merge (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
10451045
public static final fun catch (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
1046+
public static final fun catch (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
10461047
public static final fun catch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function1;
10471048
public static final fun catch (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2;
10481049
public static final fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function2;

arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,13 +832,13 @@ public sealed class Either<out A, out B> {
832832
@JvmStatic
833833
public inline fun <R> catch(f: () -> R): Either<Throwable, R> {
834834
contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) }
835-
return arrow.core.raise.catch({ f().right() }) { it.left() }
835+
return arrow.core.raise.catch(f, ::Right, ::Left)
836836
}
837837

838838
@JvmStatic
839839
public inline fun <reified T : Throwable, R> catchOrThrow(f: () -> R): Either<T, R> {
840840
contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) }
841-
return arrow.core.raise.catch<T, Either<T, R>>({ f().right() }) { it.left() }
841+
return arrow.core.raise.catch<T, _, _>(f, ::Right, ::Left)
842842
}
843843

844844
public inline fun <E, A, B, Z> zipOrAccumulate(

arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,25 @@ public inline fun <A> catch(block: () -> A, catch: (throwable: Throwable) -> A):
477477
}
478478
}
479479

480+
/**
481+
* Allows safely catching exceptions without capturing [CancellationException],
482+
* or fatal exceptions like `OutOfMemoryError` or `VirtualMachineError` on the JVM.
483+
*
484+
* Depending on the outcome of the block, one of the two lambdas is run:
485+
* - _success_ [transform] result of [A] to a value of [B].
486+
* - _thrown_ [catch] the thrown [Throwable] and calculate a value of [B].
487+
*/
488+
@RaiseDSL
489+
public inline fun <A, B> catch(block: () -> A, transform: (value: A) -> B, catch: (throwable: Throwable) -> B): B {
490+
contract {
491+
callsInPlace(block, AT_MOST_ONCE)
492+
callsInPlace(transform, AT_MOST_ONCE)
493+
callsInPlace(catch, AT_MOST_ONCE)
494+
}
495+
val value = catch({ block() }, { return catch(it) })
496+
return transform(value)
497+
}
498+
480499
/**
481500
* Allows safely catching exceptions of type `T` without capturing [CancellationException],
482501
* or fatal exceptions like `OutOfMemoryError` or `VirtualMachineError` on the JVM.
@@ -518,6 +537,25 @@ public inline fun <reified T : Throwable, A> catch(block: () -> A, catch: (t: T)
518537
return catch(block) { t: Throwable -> if (t is T) catch(t) else throw t }
519538
}
520539

540+
/**
541+
* Allows safely catching exceptions of type `T` without capturing [CancellationException],
542+
* or fatal exceptions like `OutOfMemoryError` or `VirtualMachineError` on the JVM.
543+
*
544+
* Depending on the outcome of the block, one of the two lambdas is run:
545+
* - _success_ [transform] result of [A] to a value of [B].
546+
* - _thrown_ [catch] the thrown [T] and calculate a value of [B].
547+
*/
548+
@RaiseDSL
549+
@JvmName("catchReified")
550+
public inline fun <reified T : Throwable, A, B> catch(block: () -> A, transform: (A) -> B, catch: (t: T) -> B): B {
551+
contract {
552+
callsInPlace(block, AT_MOST_ONCE)
553+
callsInPlace(transform, AT_MOST_ONCE)
554+
callsInPlace(catch, AT_MOST_ONCE)
555+
}
556+
return catch(block, transform) { t: Throwable -> if (t is T) catch(t) else throw t }
557+
}
558+
521559
/**
522560
* Ensures that the [condition] is met;
523561
* otherwise, [Raise.raise]s a logical failure of type [Error].

0 commit comments

Comments
 (0)