Error handling Kotlin vs Swift

Recently I had to implement error handling in Kotlin Multi-Platform and use it in Swift. Let's check what error handling looks like in Kotlin and compare it with Swift.

In Swift, error handling is done using the do-catch block and the throws keyword. A function that can throw an error must be marked with the throws keyword and any code that calls that function must be enclosed in a do-catch block to handle the error.

In Kotlin, error handling is done using the try-catch block and the throw keyword. A function that can throw an error must be marked with the throw keyword and any code that calls that function must be enclosed in a try-catch block to handle the error.

Both Swift and Kotlin also support the use of try? and try! to handle errors more concisely. try? Returns an optional value,  try! force-unwraps the result, and crashes the app if an error is thrown.

In addition, Kotlin has a feature called "Exceptions," similar to Swift's throwable errors, but the compiler does not enforce them. They are used more to signal that some exceptional condition occurred rather than as a mechanism for control flow.

Overall, the error-handling mechanism in both Swift and Kotlin are very similar, but Kotlin offers more flexibility with "Exceptions."

Here is an example of a function in Kotlin that throws an exception:

fun divide(numerator: Int, denominator: Int): Int {
    if (denominator == 0) {
        throw ArithmeticException("Cannot divide by zero")
    }
    return numerator / denominator
}

In this example, the divide function takes two arguments, numerator and denominator, and returns their quotient. However, if the denominator equals zero, the function throws the ArithmeticException the message "Cannot divide by zero."

To handle this exception, the calling code must be enclosed in a try-catch block:

try {
    val result = divide(10, 0)
    println(result)
} catch (e: ArithmeticException) {
    println("Error: ${e.message}")
}

This will catch the exception and print the error message "Error: Cannot divide by zero."

It's also worth noting that in Kotlin, you can use throws keywords on the function signature instead of using try-catch a block around the function call to indicate that this function might throw an exception.

When using Kotlin Multiplatform, you can pass errors from the Kotlin code to the Swift code using the Result class. The Result class is a generic class that can represent the outcome of a computation, either a value or an error.

Here is an example of how you can use the Result class to pass an error from Kotlin to Swift:

Kotlin:

fun divide(numerator: Int, denominator: Int): Result<Int, Exception> {
    if (denominator == 0) {
        return Result.failure(ArithmeticException("Cannot divide by zero"))
    }
    return Result.success(numerator / denominator)
}

In this example, the divide function returns a Result<Int, Exception> where success(T) returns the quotient and failure(E) returns the error.

Swift:

let result = divide(numerator: 10, denominator: 2)

switch result {
case .success(let quotient):
    print(quotient)
case .failure(let error):
    print(error.localizedDescription)
}

In this example, the calling code in Swift uses a switch statement to handle the result of the function call. If the result is a success, it prints the quotient. If it's a failure, it will print the error message.

You can also use other libraries or libraries that provide similar functionality like kotlinx-result .

It's worth noting that when you're working with multiplatform projects and passing data between different languages, it's essential to consider the compatibility of data types and to handle the errors properly in each language.