When do I want to renew Perl 6 exception?

Perhaps my real question is: "Is this feature suitable for learning Perl 6"? Based on If this Perl 6 CATCH block can change variables in the lexical domain? It seems that the simplest example may be beyond the scope of a simple example.

In this question, I was working with something that seems dumb or better than the other for this particular problem, because I was playing with this function and not solving the problem.

There, the documented use of warnings in the form of special types of exceptions ("control exceptions") in which you receive a message can catch it if you want, but it can also ignore it and it will resume on its own (although I was rather stupid about it in Where should I catch the Perl 6 control check exception? ).

In addition, I’m thinking about where the caller can handle a failure outside the scope of the called party. For example, reconnecting to the database, fixing missing directories and other problems with external resources for which responsibility is not responsible.

In reading these kinds of things in other languages, the advice was mainly not to use them, because in programming the "real world" people still can not cope with this problem at all.

The answer to repeating the C # exception handler in the following seems to be talking about this bad practice and ugly code. Of course, I did not understand the way to hide a bunch of code in the called one.

I cracked this example, although I'm not sure if this is a good way to do this or recommend something to beginners. The program launches the PID file when it starts. If he finds one, he throws an exception. Handling this exception verifies that another instance is still running, which may cause a different type of exception. And there is one to handle problems with the IO file. The trick is that X::MyProgram::FoundSemaphore may resume if another program is not running (but left its PID file behind).

 class X::MyProgram::FoundSemaphore is Exception { has $.filename; has $.this-pid = $*PID; has $.that-pid = $!filename.lines(1); method gist { "Found an existing semaphore file (pid {.that-pid})" } } class X::MyProgram::StillRunning is Exception { has $.that-pid; has $.os-error; method gist { "This program is already running (pid {self.that-pid})" } } class X::MyProgram::IO::OpenFile is Exception { has $.filename; method gist { "This program is already running (pid {self.that-pid})" } } sub create-semaphore { state $filename = "$*PROGRAM.pid"; END { unlink $filename } die X::MyProgram::FoundSemaphore.new( :filename($filename) ) if $filename.IO.e; my $fh = try open $filename, :w; # open throws Ad::Hoc, which could be more helpful die X::MyProgram::IO::OpenFile.new( :filename($filename), :os-error($!), # role X::IO-ish ) unless $fh; $fh.print: $*PID; } BEGIN { try { CATCH { when X::MyProgram::FoundSemaphore { my $proc = run qqw/kill -0 {.that-pid}/; X::MyProgram::StillRunning.new( :that-pid(.that-pid) ).throw if $proc.so; # exit code is 0, so, True unlink .filename; .resume; } default { say "Caught {.^name}"; exit } } create-semaphore(); } } sub MAIN ( Int $delay = 10 ) { put "$*PID sleeping for $delay seconds"; sleep $delay; } 
+7
exception perl6 resume
source share
1 answer

Renewable exceptions, of course, are not what I found in Perl 6. I don’t think I used them in userpace code yet. A throwing exception turned out to be the right way to implement the emit function used in the supply and react . The take function used in gather is also implemented using a reusable exception and, as you have already discovered, uses warn .

I suspect that the last one - warn - is the only case that a typical Perl 6 user will be interested in. Capturing alerts and sending them elsewhere - perhaps to a log file or log - is a pretty reasonable thing to do. Regarding Learning Perl 6, this is probably the obvious useful example of a renewable exception.

I find it important that all use cases that use renewable exceptions in Perl 6 are in themselves things classified as "control exceptions." Management exceptions are essentially normal exceptions at the implementation level: they include non-local transfer of control. They differ at the language level because it would be awkward to use Perl 6 if your emit , take , warn , next , last , etc. Ceased to work because of the CATCH block with default swallowing control exceptions!

However, it also does a little “what I say is not what I do”: while Perl 6 enjoys using the exception system to implement control of non-local flow, it will somewhat mask it in a dusty corner instead of keeping it in as an example of what needs to be done. And for a good reason: usually code that uses exceptions to control flow is hard to execute, and it doubles for renewable exceptions. Another big risk is that such exceptions can be swallowed by code that uses bare try or CATCH with default , which makes it a pretty fragile task in a larger code base.

I would suggest that making the best use of renewable exceptions will turn out to be an implementation strategy for things that users won't think about exceptions at all - just like with take and emit (and, most of the time, warn ). And, as is the case with existing examples of renewable exceptions, a renewable thing will be a type of exception that has been specifically designed to be thrown into renewable situations and used only when it is a reasonable thing. However, until Perl 6 provides the ability to define custom exceptions for management, I would rather not want to; the problem with swallowing try / default makes it too fragile.

+6
source share

All Articles