Package Guide

This package is designed for both beginners who are not sure how to create an exception and Julia power users who are tired of copying snippets of code containing structure definition and overloading the showerror function.

It is assumed to be used by developers inside their packages, but the proposed macro should be usable everywhere.

Installation

The package is available in the General registry, so the installation process is quite simple: from the Julia REPL, type ] to enter the Pkg REPL mode and run:

pkg> add Exceptions

Creating an exception

To create a new exception means to create a new data type that is a subtype of Exception. In the simple case, it looks like this:

mutable struct Name <: Exception
end

You can throw such an exception immediately after creation, but the error message will not be very informative:

try
  throw(Name())
catch e
  showerror(stdout, e)
end
Main.ex-Name.Name()

However, it's pretty easy to fix. As shown in the example, the error message is displayed by the showerror function, which means we can overload this function for our type:

Base.showerror(io::IO, e::Name) = print(io, "I'm gonna thrill you tonight")

Now let's check it out:

try
  throw(Name())
catch e
  showerror(stdout, e)
end
I'm gonna thrill you tonight

Okay, it's better. But what if we want to pass arguments to an exception when thrown? Not a problem, additional arguments can be specified inside the type definition. The corresponding constructor is created automatically:

mutable struct Name <: Exception
    name::String
end

Base.showerror(io::IO, e::Name) = print(io, "I'm gonna thrill you tonight, ", e.name)

try
  throw(Name("Michael"))
catch e
  showerror(stdout, e)
end
I'm gonna thrill you tonight, Michael

Okay, it's not that hard. But wait, what if you need to create twenty such exceptions? What if each of them should have a docstring with the same header and a description of fields depending on the number of arguments the exception has? That's where the macro provided by this package may be useful.

Using macro

When creating an exception set, you may encounter the fact that you need to define several similar exceptions that have the same number of arguments but differ only by names.

For example, imagine the situation that you need to create five exceptions that don't accept any arguments. For starters, we will create an auxiliary macro:

using Exceptions
@exception no_args
@no_args (macro with 1 method)

What's happened now? You have now created a helper macro that accepts as arguments a name, a documentation string, and a set of chars, strings, and expressions for the error message.

You can now create an exception like this:

@no_args e1 "Docstring" "ErrorMessage"

Yes, one line for the simplest case. Actually, let's do a few more.

@no_args e2 "Doc" * "string" "And though " "you fight " "to stay alive"
@no_args e3 string("Doc", "string") string("Your body ", "starts to shiver")
@no_args e4 sprint(print, "Docstring") join(["For no mere mortal", "can resist"], ' ')
@no_args e5 replace("Doc", "Doc" => "Docstring") ("The evil ", "of the thriller")...

As you can see, the second argument can be both a string and an exception. In doing so, both it and the third argument must yield a string. The first argument can only be a string.

Let's look at this stanza:

for e in [e2, e3, e4, e5]
    try
        throw(e())
    catch e
        showerror(stdout, e)
    end
end
Main.ex-exception.e2:
And though you fight to stay alive


Main.ex-exception.e3:
Your body starts to shiver


Main.ex-exception.e4:
For no mere mortal can resist


Main.ex-exception.e5:
The evil of the thriller

Okay, how about some arguments?

@exception one_arg name::String
@exception two_args name number::Int

@one_arg e6 "Docstring" "Gimme the cash, " e.name "!"
@two_args e7 "Docstring" "Is that a " e.name "-" e.number "? A very dangerous gun."

for e in [e6 => ("Korben",), e7 => ("Z", 140)]
    try
        throw(e.first(e.second...))
    catch e
        showerror(stdout, e)
    end
end
Main.ex-exception.e6:
Gimme the cash, Korben!


Main.ex-exception.e7:
Is that a Z-140? A very dangerous gun.

By this point, you're probably already interested in these headlines before the error messages (perhaps, in how to get rid of them). See more about this on the Customization page.