Exception Handling

The last article on this mini-series will teach you how to handle exceptions. As its one of the last steps in any project, we thought it shall also be at the end of our series. We have already seen many errors popping up, presently we will be handling them gracefully.

Throwing a fit

Sometimes the internal state of your program reaches a place where you either want to immediately notify the user, or just stop execution. In this case, you throw an exception:

julia> dontNegative(x)= x<0 ? throw(ArgumentError(x)) : print("Ok")
dontNegative (generic function with 1 method)

julia> dontNegative(-1) #This will trigger an exception
ERROR: MethodError: no method matching SystemError(::Int64)
Closest candidates are:
  SystemError(::AbstractString) at io.jl:23
  SystemError(::AbstractString, ::Integer) at io.jl:22
  SystemError(::AbstractString, ::Integer, ::Any) at io.jl:21
Stacktrace:
 [1] dontNegative(::Int64) at ./REPL[243]:1
 [2] top-level scope at REPL[244]:1

julia> dontNegative(1) #This will execute fine
Ok

Thinking of throwing a fit

There are many built-in exception types to choose from, as can be found here in the docs. But if you want to make a custom exception, you’ll have to sub-class the Exception class:

julia> struct CustomError <: Exception end

julia> throw(CustomError())
ERROR: CustomError()
Stacktrace:
 [1] top-level scope at REPL[250]:1

Sometimes the problem-causing variables can be clearly pin-pointed, and you’d like to include their value in the exception class for debugging purposes:

julia> struct RememberError <:Exception
           iPain
       end

julia> throw(RememberError(x))
ERROR: RememberError(4)
Stacktrace:
 [1] top-level scope at REPL[260]:1

Handling fits

To save the end-user from headaches, while also keeping your program running correctly, you want to handle exceptions, so as to either rectify the internal state back to something fixable, or to help the user decide what to do next:

julia> function dontNegativeElse(x)
           try dontNegative(x)
           catch e
           println("surely you didn't want to pass in a negative value there?")
					 end
       end
dontNegativeElse (generic function with 1 method)

julia> dontNegativeElse(-1)
surely you didn't want to pass in a negative value there?

We shall have the final example on finally. As in other languages, you use this keyword when you want to release a resource after you’re done with it:

julia> s="Think I'm a big resource"^10000;
       try
           #do stuff with the resource
           k=s*s;
       finally
           #release the big string for collection by the GC
           s=nothing;
       end;

julia> print(s)
nothing

Now, we’ve learnt many things in this series. And like all good things, it too must end. So, we’re taking a week long break, after which we’ll be exploring various machine learning methods in Julia. As a teaser, consider this machine learning libraries in Python rely on languages like C and C++ among others for their implementation. PyTorch for example, barely has 50% of it’s codebase in Python. Machine Learning frameworks in Julia on the other hand, are all written 100% in Julia! Making custom code not just easy to write by itself, but also allowing the whole pipeline to be in one language, and hence requiring tooling only for that one language, Julia.

That’s all, for the full story, don’t forget to check back later!

References

Leave a Reply

Your email address will not be published.