Exception handling


#1

What is a recommended way to handle exception/errors in larger projects?
Is there similar mechanism as RAII in C++ (can I be sure that a resource is cleaned if an exception is thrown; or have I always use finally and handle resource)?

Assume an exception with some additional info, see C++ example below, what is a best way in Julia…

class MyException : public std::exception
{
public:
  explicit MyException(const char* msg) :MyException(0, msg) {}
  explicit MyException(int code, const char* msg) : _code{ code }, std::exception{ msg } {}
  int code() { return _code; }

protected:
  int _code;
};

#2

The do block syntax is often used as a way to create context managers or give RAII-like behavior. For example, Julia provides this definition for you:

function open(f::Function, args...)
    io = open(args...)
    try
        f(io)
    finally
        close(io)
    end
end

which allows a user to write code like:

open("foo.txt") do f
  write_some_data_into_a_file(f)
end

and ensures that the file is properly closed no matter what the user’s code does. You could implement the same pattern for the resources in your code.


#3

Thanks, it seems that RAII-like behavior is not a built in feature in Julia.

I’m trying to find a general way how to handle errors in an a larger project.

The do block syntax is nice to use once, but it seems, it has to be always wrapped in the do block. Assume a simple C++ code: (I know the design of opening a file and do something in between is not a correct way, but such a code is common in everyday life) A comparison of C++ (assuming C++ 11 or higher) and Julia follows:

void foo()
{
  std::ifstream f;
  f.open("foo.txt");
  // do something or call something that throws and write results....
} // whatever happens the resource is closed

in Julia I have to do following to achieve the same safety:

import Base:open
function open(f::Function, args...)
    io = open(args...)
    try
        print_with_color(:green, "writing...\n")
        f(io)
    finally
        print_with_color(:blue, "closing.\n")
        close(io)
    end
end

function foo()
  open("foo.txt") do f
     # do something, call something that throws and write results....
     # I have to be sure to write into the file here
  end # the file is closed here I cannot use it any more
  
end

#4

One additional option that’s been suggested here before is Defer.jl which provides some helpful macros for scoping and resource cleanup.


#5

Thanks for hint, I’m gonna check the Defer.jl in more details. Though, the intro confirmed, that the resource handling is one of the key features for development.


#6

Here is proposed error handling for larger project.

We define custom exception, used for our code…

type MyException <: Exception
    code::Int64
    msg::String
    
    function MyException(code::Int64, msg::String)
        new(code, msg)
    end
end

fnThrow is our main function where we call a lot of code in try catch block

function fnThrow(fn::Function)
    try
        fn()
    catch exc
        if(isa(exc, MyException))
            print_with_color(:green, "$exc\n")
        elseif(isa(exc, Exception))
            print_with_color(:yellow, "$exc\n")
        else
            print_with_color(:red, "! $exc\n")
        end
    end
end

and testing the error handling

fn1() = sqrt(-1)
fn2() = throw(MyException(11, "throwing"))
fn3() = throw(Exception("exception"))
fn4() = error("error")
fn5() = throw("string")
fn6() = throw(1)

fnThrow(fn1)
fnThrow(fn2)
fnThrow(fn3)
fnThrow(fn4)
fnThrow(fn5)
fnThrow(fn6)