You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 14, 2024. It is now read-only.
Copy file name to clipboardExpand all lines: _posts/2023-05-03-functional-error-handling-in-kotlin.md
+5-85Lines changed: 5 additions & 85 deletions
Original file line number
Diff line number
Diff line change
@@ -347,7 +347,9 @@ The Arrow DSL applies the same syntax for all the types we can use to handle err
347
347
For nullable type, Arrow offers the `nullable` DSL. We can access helpful functions inside the DSL, such as the `ensureNotNull` function and the `bind` extension function. Let's rewrite the `sumSalaries` function using the `nullable` DSL, adding a few logs that we'll use to understand what's going on:
As we can see, the two functions extract the value from the nullable type. If the value is `null`, then the `nullable.eager` block returns `null` immediately. Here, we use the `eager` function, which accepts a not-suspendable function. We can use the `nullable` DSL directly to use a suspendable function (in the upcoming version 2.0 of Arrow, there will be only a single `nullable` DSL managing both cases).
363
+
As we can see, the two functions extract the value from the nullable type. If the value is `null`, then the `nullable` block returns `null` immediately. In the version 2.0 of Arrow, the `nullable` DSL manages both normal and suspend functions inside.
362
364
363
365
We can give the function a job id that doesn't exist, and then we can check its behavior:
364
366
@@ -381,88 +383,6 @@ The sum of the salaries using 'sumSalaries' is 0.0
381
383
382
384
As we might expect, the function returns `null` immediately after searching for the `JobId(42)` returns `null`.
383
385
384
-
Both the `nullable` and the `nullable.eager` DSL have a scope as the receiver, respectively an `arrow.core.continuations.NullableEagerEffectScope`and an `arrow.core.continuations.NullableEffectScope`:
The function `ensureNotNull` is an extension function defined on the scope `NullableEagerEffectScope` that calls the same function defined on the scope `EagerEffectScope`, from which it inherits:
398
-
399
-
```kotlin
400
-
// Arrow SDK
401
-
@OptIn(ExperimentalContracts::class)
402
-
publicsuspendfun <B> NullableEffectScope.ensureNotNull(value:B?): B {
403
-
contract { returns() implies (value !=null) }
404
-
return ensureNotNull(value) { null }
405
-
}
406
-
407
-
@OptIn(ExperimentalContracts::class)
408
-
publicsuspendfun <R, B:Any> EagerEffectScope<R>.ensureNotNull(value:B?, shift: () ->R): B {
409
-
contract { returns() implies (value !=null) }
410
-
return value ?: shift(shift())
411
-
}
412
-
```
413
-
414
-
The `shift` function basically short-circuits the execution of the effect that calls it. In the case of the `NullableEffectScope` effect, returning `null` immediately.
415
-
416
-
417
-
The `bind` is declared as a member extension function in the `NullableEagerEffectScope` class, making it available only inside the scope created using an object of type `NullableEagerEffectScope`:
In Kotlin, we said that the `NullableEagerEffectScope` is the **dispatch receiver** of the `bind` function, whereas the `B?` type is the **extension receiver**. In reality, the `bind` function is just a wrapper to the same function defined in the `Option` type that we'll see in the next section.
439
-
440
-
Another useful member extension function of the `NullableEagerEffectScope` is the `ensure` function:
The above function uses the more general `ensure` function defined in the `EagerEffectScope` class, which shift the value of the computation to a generic given value if the given condition is not satisfied:
In detail, the function verifies the given condition. It short-circuits the execution inside the scope to `null` if the condition is unmet. To give an example, we can change the function that converts USD to EUR, returning `null` if the given amount is negative:
Although nullable types offer a reasonable degree of compositionality and full support by the Kotlin language, there are some cases when you can't use it to handle errors. There are some domains where the `null` value is valid, and we can't use it to represent an error. Other times, we need to work with some external libraries that don't support nullable types, such as RxJava or the project Reactor.
467
387
468
388
Fortunately, Kotlin and the Arrow library provide a lot of alternatives to handle errors functionally. Let's start with the `Option` type.
Last but not least, the `nullable` DSL we've seen in the previous section integrates smoothly with the `Option` type. In this case, the `bind` function called on a `None` type will eagerly end the whole block returning a `null` value:
0 commit comments