Exception handling

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;
};

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.

2 Likes

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

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

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.

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)