Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CATCH and throw in custom exception

Tags:

raku

Should 'CATCH' be called strictly after 'throw'?

Example 1:

say 'Hello World!';

class E is Exception { method message() { "Just stop already!" } }

CATCH {
    when E {
            .resume;
    }
}

E.new.throw;

Error:

Cannot find method 'sink': no method cache and no .^find_method in block at /tmp/739536251/main.pl6 line 11

Example 2:

say 'Hello World!';

class E is Exception { method message() { "Just stop already!" } }

E.new.throw;

CATCH {
    when E {
            .resume;
    }
}

No error

like image 600
Shniperson Avatar asked Sep 21 '19 14:09

Shniperson


People also ask

Can we throw custom exception in catch block?

You can throw it in your code and catch it in a catch clause. And you can but don't need to specify if your method throws it.

Can we catch custom exception in Java?

Basically, Java custom exceptions are used to customize the exception according to user needs. In simple words, we can say that a User-Defined Exception or custom exception is creating your own exception class and throwing that exception using the 'throw' keyword.

How do you throw and catch exception?

catch blocks A catch-block will catch a thrown exception if and only if: the thrown exception object is the same as the exception object specified by the catch-block. the thrown exception object is the subtype of the exception object specified by the catch-block.

Can we catch and throw the same exception?

Generally, you catch many exceptions, generalize them into one and throw it.. So that all similar exceptions can be handled in the same way..


2 Answers

It's an already filed .resume bug.


The error message isn't the most awesome P6 has ever produced but it isn't technically LTA because it is descriptive and related to the error (caused by the bug).


CATCH and throw in custom exception

I think it's just a .resume bug rather than being about custom exceptions.

Should 'CATCH' be called strictly after 'throw'?

No, that's not the issue. (That said, putting it after the .throw just so happens to avoid this bug; I'll return to that later.)


In the code that goes boom, you throw an exception, then .resume in response to it. Per the doc .resume:

Resumes control flow where .throw left it

Which in this case means where the arrow points:

E.new.throw ;
           🡅

Now, consider this program:

42;

If you run that program you'll see:

Useless use of constant integer 42 in sink context (line 1)

That's because Raku applies "sink context" rules when deciding what to do at the end of a statement. Applying sink context entails calling .sink on the value produced by the statement. And for 42 the .sink method generates the "useless" warning.

But what's the value of a .resumed thrown exception?

class E is Exception {}
CATCH { when E { .resume } }
say E.new.throw.^name; # BOOTException
E.new.throw.sink;      # Cannot find method 'sink':
                       # no method cache and no .^find_method

It turns out it's a BOOTException object which isn't a high level Raku object but instead a low level VM object, one that doesn't have a .sink method (and also stymies P6's fallback methods for finding a method, hence the "I tried everything" error message).


So why does putting the CATCH block after the throw make a difference?

It seems the bug only occurs if the throw statement is the last statement. This works fine, just displaying 42:

class E is Exception {}
CATCH { when E { .resume } }
E.new.throw;
say 42;

As you presumably know, Raku treats the last statement of a block specially. Perhaps this bug is related to that.

like image 105
raiph Avatar answered Nov 12 '22 03:11

raiph


CATCH must be in same block.

Problem in the first example is that no E but another exceptions is thrown. Try

class E is Exception { method message() { "Just stop already!" } };

CATCH {
    when E {
        .resume;
    }
    default { say .perl }
}

E.new.throw;

you could change when block

class E is Exception { method message() { "Just stop already!" } };

CATCH {
    when E {
        say .message;
    }
}

E.new.throw;

or definition of the class E, e.g.

class E is Exception { 
    has $.resume; 
    method message() { "Just stop already!" } 
};

CATCH {
    when E {
        say .resume;
    }
}

E.new(resume => 'stop here').throw;
like image 42
wamba Avatar answered Nov 12 '22 04:11

wamba