Hi,
How multiple exception types can be handled by a single except clause? The below options do not compile in Nim 1.6.2
Option 1
try:
...
except OSError or IOError as e:
...
Option 1a
try:
...
except OSError | IOError as e:
...
Option 2
try:
...
except OSError, IOError as e:
...
Option 2a
try:
...
except (OSError, IOError) as e:
...
Is there an alternative way to handle multiple exception types in a single except clause? If there is no alternative, would you consider any of the above options to be added to the Nim language?
Thank you, Volodymyr
I think you can pass an array of exceptions:
except [ValueError, RuntimeError]
When passing an array of exceptions the compilation fails with
Error: type expected, but got: [OSError, IOError]
You cannot handle it in a single exception clause, you need multiple except branches as such:
try:
raise newException(OsError, "Hello")
raise newException(IoError, "Hello")
except OsError as e:
echo e.msg, " OS"
except IoError as e:
echo e.msg, " Io"
@volodymyr - The assignment sugar "as e:" does not work with the inline type array. So, you may need to do this instead:
try: discard open("hi")
except [IOError, OSError]:
let e = getCurrentException()
echo "message is: ", e.msg
I tried @moigagoo's example and it seemed to work. Changing IOError to ValueError meanwhile also let the missing file exception bubble up.
{ Personally, were it me, I would have used the sum type syntax, IOError|OSError and tried to make the as ident work, but many might also say @ElegantBeef's is better "style". }
The motivation of handling multiple exception types in a single except clause is to avoid code duplication and potential security flaws when the same exception handling is applicable to multiple, but different exception types.
The current exception handling design implies code duplication or creation of otherwise unnecessary exception handling function.
Would the community consider any of the above proposed options to be added to the Nim language?
Thank you, @cblake, for your solution! Tt works and avoids code duplication, but at cost of less elegant syntax [OSError, IOError] (compared to the initially proposed options) and explicit let e = getCurrentException().
The initially proposed options are more elegant and add flexibility to Nim's exception handling. I'd like see them to be considered for Nim 2.0!
This works just fine:
try:
raise newException(OsError, "Hello")
raise newException(IoError, "Hello")
except OsError, IoError:
echo getCurrentExceptionMsg(), " Something"
You cannot name the exception then as it's not clear which type it should have.
And a tip: If you want a feature implemented don't say "security!", it's bad for your credibility.
This solution is fine! Thank you! The reason that the exception cannot be named is reasonable enough. Polymorphic behavior of error type is safely managed inside the error handler.
Thank you!
Well it could have the same behaviour as getCurrentException(), ie. return a generic ref Exception which you then have to upcast to the correct exception. The problem is just that you don't have anything to get the actual type from, maybe this could somehow be passed in so we could do something like:
try:
raise newException(OSError, "Hello")
except OsError, IoError as e, kind:
let msg =
when kind is OSError:
"OSError " & $(ref OSError)(e)
else:
"IoError " & $(ref IOError)(e)
echo msg
Or it could support multiple types, but then you have to pass multiple identifiers:
try:
raise newException(OSError, "Hello")
except OsError, IoError as ose, ioe:
if not ose.isNil:
echo "OSError " & $ose
else:
echo "IOError " & $ioe
Alternatively it could also be syntactic sugar which simply copies the body across multiple except statements, except OSError, IOError as e would just copy the body into two separate except OSError as e and except IOError as e bodies. Then you could use when e is OSError like you would do in a generic proc that handles two alternative types. This is probably the most ergonomic and Nim-like, since it does pretty much the same as the existing generic procedures.
I think that one exception type per except clause is a cleaner solution than grouping multiple exception types in a single except clause and than case/of inside the exception handler.
The idea of syntactic sugar of except OSError, IOError as e which copies the body of exception handler into separate except clauses is very useful and interesting, as it would be the most ergonomic and Nim-like solution for the initial exception handling problem and it would be a backward compatible language extension that provides more uniform exception handling by allowing named exception even in the case of different exception types in a single except clause