Learning Nim: Exception Handling - I
Tags: nim, errors, tutorial, learn
Published: 2020-02-22 06:33:29

I began exploring about it in [Nim's manual](https://nim-lang.org/docs/manual.html#exception-handling) and loved the concept of [effect systems](https://nim-lang.org/docs/manual.html#effect-system). I'll probably do one more post about it in the future.

```nim
# What's Refreshing: No divide by zero error
var a = 0
echo -89/a #-Inf
echo NegInf > Inf #false
```
## **Usual Try, Except, Finally**
```nim
from strutils import parseInt

try:
    var x = parseInt("133a")

except ValueError as e:
    echo "We made an error: ", e.msg #We made an error: invalid integer: 133a

    #For when we don't use 'as e'
    var error = getCurrentException() 
    echo error.msg #invalid integer: 133a

    #If we're in a hurry
    echo getCurrentExceptionMsg() #invalid integer: 133a

finally:
    echo "I will get executed regardless of an error" 
```
## **Custom Exceptions**
```nim
type MyException* = object of Exception
if(1 == 1):
    raise MyException.newException("This Exception is mine!! Get your own!")
    #OR raise newException(MyException, "This Exception is mine!! Get your own!")
```
The `*` is there so that `MyException` is visible to other modules too.
#### But can we raise predefined errors with custom messages?
```nim
raise newException(IOError, "This is IO speaking, Er Yes you can!")
```
## **Try Expression**
```nim
from strutils import parseInt
let x = try: parseInt("133a")
        except: -1
        finally: echo "hi"

echo x
```
`try` `except` and `finally`(optional) works as they do, and you get to dynamically decide the value of x in a single expression. But you cannot use multi-line code inside the try-except block. You can, in finally block. 

*Note: There are also [defer statement](https://nim-lang.org/docs/manual.html#exception-handling-defer-statement) which I haven't covered here*

## **Exception Tracking**
Who knew you can explicitly define what exceptions your proc/iterator/method/converter can raise!
```nim
proc p(what: bool) {.raises: [IOError, OSError].} =
  if what: 
    raise newException(ValueError, "It won't compile") #ERROR
  
p(true) 
``` 
The compiler won't let you raise any error that's not defined.
#### What if we try a custom exception?
```nim
type MyException = object of ValueError
proc p(what: bool) {.raises: [IOError, OSError].} =
  if what: 
    raise newException(MyException, "Still won't compile") #ERROR
  
p(true) 
``` 
#### What if my custom exception was generic type?
```nim
type MyException = object of Exception

proc p(what: bool) {.raises: [IOError, OSError].} =
  if what: 
    raise newException(MyException, "Still won't compile") #ERROR
    
p(true)
```
#### What if I design the code to throw an undefined error?
```nim
from strutils import parseInt

proc p(what: bool) {.raises: [IOError, OSError].} =
  
  var a = parseInt("133a") #Throws ValueError usually
  echo a
  
p(true) #Still doesn't work
```
That's it. I need more experience with it to completely understand the [effect system](https://nim-lang.org/docs/manual.html#effect-system) and then I'll be back with part II post.

If you learnt something from this post, hit ❤️ and share! Others deserve to know about it too!