Thread overview
Feature idea: scope (failure, ExceptionSpecification) for catching exceptions
Mar 26, 2015
Andrej Mitrovic
Mar 26, 2015
Vladimir Panteleev
Mar 28, 2015
Andrej Mitrovic
Mar 26, 2015
w0rp
Mar 27, 2015
Jacob Carlborg
March 26, 2015
One idea I'd like to see is to enhance scope(failure) to allow it to catch a specific type of exception which would allow us to e.g. log the exception message and potentially re-throw the exception. All of this without having to nest our code in try/catch statements.

So instead of having code such as the following:

-----
void test ( )
{
    try
    {
        prepare();
        foo();
        finish();

        try
        {
            prepare();
            bar();
            finish();
        }
        catch (MyException ex)
        {
            logger.log("bar() failed with: " ~ ex.msg);
            throw ex;
        }
    }
    catch (MyException ex)
    {
        logger.log("foo() failed with: " ~ ex.msg);
        throw ex;
    }
}
-----

-----
void test ( )
{
    scope (failure, MyException ex)
    {
        logger.log("foo() failed with: " ~ ex.msg);
        throw ex;
    }

    prepare();
    foo();
    finish();

    scope (failure, MyException ex)
    {
        logger.log("bar() failed with: " ~ ex.msg);
        throw ex;
    }

    prepare();
    bar();
    finish();
}
-----

Granted it's not the best example out there, but I think it has potential. Thoughts?
March 26, 2015
On Thursday, 26 March 2015 at 11:23:34 UTC, Andrej Mitrovic wrote:
> Granted it's not the best example out there, but I think it has
> potential. Thoughts?

Your example will print the exception message 2 (or 3) times. Is this really necessary?

I've found that

scope(failure) log("Failure while transmogrifying " ~ victim ~ ":");

is often sufficient. Assuming the exception will be caught and logged to the same output as the log line above, it'll show up right before the exception details, thus giving the needed context.

What is your use case for only logging specific exception types?

It would be nice if we could add arbitrary information to in-flight exceptions themselves. E.g. a nicer way to do something like this:

 try
   transmogrify(victim);
 catch (Exception x)
 {
   x.msg = "Failure while transmogrifying " ~ victim ~ ":\n" ~ msg;
   throw x;
 }

I've also tried a different approach, using chained exceptions:

https://github.com/CyberShadow/ae/blob/master/utils/exception.d#L68-L91
March 26, 2015
I think I'd tend towards not adding this feature. It seems like it's just a logging problem, and try-catch is probably enough for that.
March 27, 2015
On 2015-03-26 12:23, Andrej Mitrovic via Digitalmars-d wrote:
> One idea I'd like to see is to enhance scope(failure) to allow it to
> catch a specific type of exception which would allow us to e.g. log
> the exception message and potentially re-throw the exception. All of
> this without having to nest our code in try/catch statements.

Sounds like you want a catch statement without being tied to a try statement. Something like this exists in Ruby:

With begin/end:

def foo
  begin
    raise 'foo'
  rescue Exception => E
    p e
  end
end

Without:

def foo
  raise 'foo'
rescue Exception => E // tied to the function scope
  p e
end

In the above example the "rescue" is tied to the function scope. Something similar could be supported in D:

void foo ()
{
  throw new Exception("foo");

  catch (Exception e) // tied to the function scope
    writeln(e);
}

Or possibly tie it to the most enclosing scope:


void foo ()
{
  {
    throw new Exception("foo");

    catch (Exception e) // tied to the scope
      writeln(e);
  }
}

I wouldn't mind if this was supported.

-- 
/Jacob Carlborg
March 28, 2015
On 3/26/15, Vladimir Panteleev via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> What is your use case for only logging specific exception types?

We already have scope(failure) with its defined semantics (it will not
swallow the exception), changing that would be bad. So the only
workable solution I see is to extend it via 'scope(failure,
ExceptionType ex)'.

It's not that I want to catch specific exceptions, but instead I really love using scope but often find myself wishing I could catch the exception, swallow it (not rethrow it) and log it, without a try/catch.

Sometimes you're not allowed to propagate an exception (think nothrow functions, functions that interact with C, functions invoked in different threads, etc), so you have to try/catch and use logging. I kind of think extending scope could make this nicer to work with.

It was just a passing thought, though. :)