gpt4 book ai didi

exception - 我什么时候想要恢复 Perl 6 异常?

转载 作者:行者123 更新时间:2023-12-04 12:04:40 25 4
gpt4 key购买 nike

也许我真正的问题是“这是否适合学习 Perl 6”?基于 Should this Perl 6 CATCH block be able to change variables in the lexical scope? ,似乎最简单的例子可能超出了一个简单的例子。

在那个问题中,我正在研究一些看起来很愚蠢的东西,或者以另一种方式更好地解决那个特定问题,因为我是在玩这个功能而不是解决问题。

有记录使用警告作为特殊类型的异常(“控制异常”),您可以在其中获取消息,可以根据需要捕获它,但也可以忽略它并且它会自行恢复(尽管我对此很愚蠢在 Where should I catch a Perl 6 warning control exception? 中)。

除此之外,我正在考虑调用者可以处理被调用者范围之外的失败的事情。例如,重新连接到数据库、修复丢失的目录以及被调用者不负责的其他外部资源问题。

在阅读其他语言中的此类内容时,建议主要是不要使用它们,因为在“现实世界”编程中,人们往往不会实际处理问题。

C# exception handler resume next的答案似乎说这是不好的做法和丑陋的代码。我当然还没有想出在被调用者中隐藏一堆代码的方法。

我修改了这个例子,虽然我不相信这是一个很好的方法或者推荐给初学者的东西。程序在启动时查找 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;
}

最佳答案

我发现自己在 Perl 6 中肯定不会用到可恢复异常。我认为我根本没有在“用户空间”代码中使用它们。一个可恢复的异常被证明是实现 emit 的正确方法函数,用于 supplyreact块。 take gather中使用的函数也使用可恢复异常实现,并且 - 正如您已经发现的 - warn使用它们。

我怀疑最后一个 - warn - 是典型的 Perl 6 用户会感兴趣的唯一情况。捕获警告并将它们发送到其他地方 - 可能是日志文件或日志服务器 - 是需要做的相当合理的事情。就 Learning Perl 6 而言,这可能是可恢复异常的明显有用示例。

我认为重要的是,所有利用 Perl 6 中可恢复异常的用例都被归类为“控制异常”。控制异常本质上是实现级别的正常异常:它们涉及非本地控制转移。它们在语言级别上是不同的,因为如果您的 emit 使用 Perl 6 会相当尴尬。 , take , warn , next , last由于 CATCH 等原因停止工作带有 default 的块吞下控制异常!

然而,它也有点“照我说的做,而不是我做的”:虽然 Perl 6 很乐意使用异常系统来实现非本地流控制,但它在某种程度上将其隔离在语言的一个尘土飞扬的角落,而不是而不是举起它作为做某事的例子。并且有充分的理由:通常,使用异常进行流控制的代码很难遵循,而对于可恢复的异常来说,这会加倍。另一个大风险是,使用裸 try 的代码可能会吞没此类异常。或 CATCHdefault - 在更大的代码库中做这件事是一件相当脆弱的事情。

我认为可恢复异常的最佳用途将成为用户根本不会考虑异常的事情的实现策略 - 就像 take 的情况一样。和 emit (而且,大多数情况下, warn )。并且,与现有的可恢复异常示例一样,被恢复的事物将是一种异常类型,专门设计用于在可恢复情况下抛出,并且仅在明智之举的情况下使用。然而,在 Perl 6 提供一种定义自定义控件异常的方法之前,我不太愿意这样做; try/default吞咽问题使它太脆弱了。

关于exception - 我什么时候想要恢复 Perl 6 异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43304911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com