@user Is there a cleaner way to write this code? I've got a method that returns an Option, and I want it to print an error message and return None if an error was thrown during the computation, or return Some(value) if the computation successfully returned a value.
try {
Some(computeValueAndPossiblyError(arg1, arg2))
} catch {
case anException: AnException =>
println("some error message")
return None
case anotherException: AnotherException =>
println("some other error message")
return None
case differentException: DifferentException =>
println(differentException.getMessage)
return None
}
The return None gets repetitive (my actual code has ten different exceptions it tests for). Is there a way to write it only once?
scala.util.Try could help you here, gimme a minute to make a Scastie
You could go the imperative way like this, but I don't like return. On the other hand, I can't figure out how to use Try nicely without resorting to toEither and then converting to an Option
You could catch all exceptions and then pattern match later, but that might end up with you catching exceptions you aren't going to handle (Scastie)
Yeah, I'd rather stay specific with my exception catching.
The other part that I haven't mentioned is that I also have another try catch earlier in the method, which also has return None if there's an exception at that point. So there, the return part is important because it needs to skip the rest of the function.
If all of your custom exceptions inherit from the same abstract class, you could modify the abstract class to have some def message method, and then just do case hblException: HBLException => println(hblException.message)
But yeah, returning the result would be a nicer way to do it, and I think you don't even need to throw exceptions. Perhaps you could return an Either[HBLMessage, List[Something]] from processArgs
With that, you don't have to worry about catching unnecessary exceptions, you could just map/pattern match on that Either to get what you want
@user Probably a good idea to have a base HBLException, yeah. It wouldn't be quite as simple as println(hblException.message), because I have slightly different messages for errors thrown during argument parsing vs. during program execution, but maybe I could standardize those a bit.
@user Oh, yeah, I reckon I could move that first try/catch into processArgs, couldn't I? That would be cleaner. I'd probably have it return an Option[Seq[HBLAny]]
@user Currently, they're always run from a file. I have vague ideas of adding a REPL in the future, but that would only work in Thimble mode.
By the way, are you expecting HBL to be somewhat sane and have errors for people doing things like dividing by 0?
If not, you could move ArithmeticException into those methods
On second thought, catching all exceptions might actually be a good idea. Correct me if I'm wrong, but the way it is now, it seems like a RandomException would crash the entire HBL interpreter and show only a scary stacktrace to the user, whereas handling it would allow you to say "Hey, this exception occurred, here's a short summary, use this flag to get the full stacktrace. No worries, though, you can go fix your program and your friendly neighborhood HBL interpreter will be right here"
Python takes you on a date, talks to you for a while, and its issues slowly start to show up. JS shakes your hand, punches you in the face, and then is fairly normal from then on.
Vis-a-vis dividing by zero specifically, the plan is to introduce an HBLRational type that includes values 1/0, -1/0, and 0/0. So dividing by zero won't be an error.
Lyxal found this Scala library (it's quite a bit more than that, though, I think it also provides its own language). Might be too heavy a dependency for you but could be possibly useful for number stuff
(it doesn't have binaries for Scala 3, but I believe you can use CrossVersion in sbt somehow to get it to work)