也许我真正的问题是“这个功能是否适合学习 Perl 6“? 基于这个 Perl 6 CATCH 块应该能够更改词法范围内的变量吗? https://stackoverflow.com/q/43289842/2766176,看起来最简单的例子可能超出了简单的例子。
在这个问题中,我正在处理一些看起来很愚蠢的东西,或者更好地以另一种方式解决该特定问题,因为我正在使用该功能而不是解决问题。
有记录使用警告作为特殊类型的异常(“控制异常”),您可以在其中获取消息,如果您愿意,可以捕获它,但也可以忽略它,它会自行恢复(尽管我对此相当愚蠢)在我应该在哪里捕获 Perl 6 警告控制异常? https://stackoverflow.com/q/43243412/2766176).
除此之外,我正在考虑调用者可以处理被调用者范围之外的故障的事情。例如,重新连接到数据库、修复丢失的目录以及被调用者不负责的其他外部资源问题。
在阅读其他语言的此类内容时,建议大多是不要使用它们,因为在“现实世界”编程中,人们往往不会真正处理问题。
答案是C# 异常处理程序继续下一步 https://stackoverflow.com/a/42202288/2766176似乎是说这是糟糕的实践和丑陋的代码。我当然还没有找到在被调用者中隐藏一堆代码的方法。
我修改了这个例子,尽管我不相信这是一个好方法,也不值得推荐给初学者。程序启动时会查找 PID 文件。如果找到,就会抛出异常。处理该异常会检查另一个实例是否仍在运行,这可能会引发不同类型的异常。并且,还有一个可以处理文件 IO 问题的工具。诀窍是X::MyProgram::FoundSemaphore
如果其他程序没有运行(但留下了其 PID 文件),则可以恢复。
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;
}