-1

I am having trouble refactoring this function here. How can I make it functional, in a way that instead of nested when-is you have sequential mappings/aggregations of LEFT=ErrorCodes? And if I wanted to add a try-catch-block to it, how would I make that functional? I am using 1.2.0-RC but have no objections downgrading it.

when(val maybeValid = ValidInput.create(uncheckedInput)) {
    is Either.Right -> {
        val validInput = maybeValid.value
        when(val maybeResult = Result.create(validInput)) {
            is Either.Right -> {
                TRY/CATCH, RETURN LEFT ON CATCH, RESULT ON RIGHT
            }
            is Either.Left -> { RETURN LEFT })) }
        }
    }
    is Either.Left -> maybeValid.leftOrNull()!!.map { RETURN LEFT }
}

I am just a bit overwhelmed of the toolset Arrow offers, originally I was just using Either as an advanced tuple, but I might as well aggregate the results in the way it is meant to be used.

Phil
  • 7,065
  • 8
  • 49
  • 91

1 Answers1

2

You can refactor the nested when expressions to a more functional style by using map, flatMap, and fold. Additionally, you can use Try to handle exceptions in a functional manner. Here's a refactored version of your code that's more functional and includes a try-catch block using the Try class:

fun processInput(uncheckedInput: String): Either<ErrorCodes, Result> {
return ValidInput.create(uncheckedInput)
    .flatMap { validInput ->
        Result.create(validInput)
            .flatMap { result ->
                Try {
                    // Perform the operation that might throw an exception
                    // Replace with your actual operation
                }.fold(
                    { throwable -> ErrorCodes.ExceptionError(throwable).left() },
                    { result.right() }
                )
            }
    }

}

Here's what the code does:

  • It starts by creating a ValidInput from the uncheckedInput. If it's successful, it proceeds to the next step using flatMap.

  • It tries to create a Result from the validInput. If it's successful, it proceeds to the next step using flatMap.

  • It uses the Try class to handle the exception in a functional manner. If the operation within the Try block throws an exception, it returns a Left with an ErrorCodes.ExceptionError. If the operation is successful, it returns a Right with the result.

This approach should give you a more functional and cleaner code structure, and you can easily add more steps to the process using flatMap if needed.

Syxs
  • 158
  • 6
  • Thanks, I applied your code. But the functional error catching was deprecated in 1.2.0-RC, it seems a regular try-catch-block is recommended now – Phil May 06 '23 at 15:43