Home United States USA — software Kotlin: Functional Exception Handling With Try

Kotlin: Functional Exception Handling With Try

199
0
SHARE

Much like Scala, you can use the Try type in Kotlin to functionally handle exceptions. This guide walks through a basic setup and introduces chaining with maps.
Scala has a Try type to functionally handle exceptions. I wrapped my head around that concept by using the excellent Neophyte’s guide to Scala by Daniel Westheide. This post will replicate that type using Kotlin.
Consider a simple function that takes two Strings, converts them to integers, and then divides them (sample based on Scaladoc of Try):
It is the caller’s responsibility to ensure that any exception that is propagated from this implementation is handled appropriately using the exception handling mechanism of Java/Kotlin:
My objective with the « Try » code will be to transform the « divide » into something which looks like this:
A caller of this variant of the « divide » function will not have an exception to handle through a try/catch block. Instead, it will get back the exception as a value, which it can introspect and act on as needed.
The « Try » type has two implementations corresponding to the « Success » path or a « Failure » path and is implemented as a sealed class the following way:
The « Success » type wraps around the successful result of an execution while the « Failure » type wraps any exception thrown from the execution.
So now, to add some meat to these, my first test is to return one of these types based on a clean and exceptional implementation, along these lines:
This can be achieved through a « companion object » in Kotlin, similar to static methods in Java. It returns either a Success type or a Failure type based on the execution of the lambda expression:
Now that a caller has a « Try » type, they can check whether it is a « Success » type or a « Failure » type using the « when » expression like before, or using « isSuccess » and « isFailure » methods, which are delegated to the sub-types like this:
In case of Failure, a default can be returned to the caller, something like this in a test:
Again implemented by delegating to the subtypes:
The biggest advantage of returning a « Try » type, however, is in chaining further operations on the type.
A « map » operation is passed a lambda expression to transform the value in some form — possibly even to a different type:
Here, a number is being doubled and then converted to a string. If the initial Try were a « Failure », then the final value will simply return the « Failure » along the lines of this test:
Implementing « map » is fairly straightforward:
flatMap, on the other hand, takes in a lambda expression, which returns another « Try » type and flattens the result back into a « Try » type along the lines of this test:
Implementing this is simple too, along the following lines:
The « map » and « flatMap » methods are the power tools of this type, allowing chaining of complex operations together and focusing on the happy path.
Try is a powerful type, allowing a functional handling of exceptions in code. I have a strawman implementation using Kotlin available in my GitHub repo here.

Continue reading...