1

I have handled exception as follows:

def calculate(input: Option[Double]): Try[String] =
  Try {
    input match {
      case (Some(value)) => value.toString
      case (None) => throw new IllegalArgumentException("No value found")
    }
}

And in client code:

val result = calculate(....)

result match {
    case Success(i) => println(i)
    case Failure(s) => throw s // or log(s) to log the issue and continue
}

Is it good enough practice or much better can be done for clean and elegant code base?

1 Answer 1

8

Try usually used to cover parts which might throw an error, like in cases if you are using some Java libs, which can throw an exception. But, if you would like to return possible error and force client to handle it, Either[A, B] is much better option, at least because you can specify more precise error type for Left[A] and safely to pattern match over your's A type, instead of do possibly incorrect pattern matching against some Throwable, like you would do for Failure(t).

So, in your case possible solution would look like:

sealed trait CalculationError
case class Error1(cause: String) extends CalculationError

def calculate(input: Option[Double]): Either[CalculationError, String] =
    input match {
      case (Some(value)) => Right(value.toString)
      case (None) => Left(Error1("No value found"))
    }
}

val result = calculate(....)

result match {
    case Right(i) => println(i)
    case Left(Error1(s)) => println(s)
}

This is safer approach, because you can later add another type of error , say case class Error2(cause: String) extends CalculationError and on client pattern matching code part, compile will show a warn message that you missed handling of new error: Match is not exhaustive. In case of Failure(t) compile won't be able suggest such warning, so it's easier to make mistake on error handling side.

Hope this helps!

Sign up to request clarification or add additional context in comments.

7 Comments

Option#toRight might shorten it like so: input.map(_.toString).toRight(Error1("No value found"))
No need to fix it, it is just an alternative :)
While handling case Right, if we want to assign i to some variable and use it later on, then it violates immutability. Can we avoid it somehow?
@Mandroid Thank you for a comment, Could you provide more details how result will be used? Is this part of HTTP request handling, CLI app arguments handling, message handling from some queue or you are interesting about about abstract response?
So basically I am iterating a Seq, and for each element I call calculate. If result of calculate has error,then I would log the error and move to next element, ELSE I would use value inside Right for further processing and results of those computations are put inside another object, which is then returned to client.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.