Eug*_*ash 76 perl exception-handling
Perl社区的共识似乎Try::Tiny是处理异常的首选方式.
Perl的5.14(这是我使用的版本)似乎解决的问题与eval该Try::Tiny地址.还会Try::Tiny为我提供任何好处吗?
bri*_*foy 34
我的回答是不受欢迎的,但我不认为Perl程序员应该尝试使用我们在Perl中称为"异常"的极其糟糕的概念.这些基本上是侧通道返回值.然而,仍然迷恋于异常的概念,即使使用全局变量来传递状态的所有复杂性,人们仍然试图使其工作.
然而,实际上,人们会die用来表示失败.有些人会说你可以die使用引用并传回错误对象,但你不需要这样做die.我们有对象,所以我们应该使用对象的所有功能:
sub some_sub {
...
return Result->new( error => 1, description => ... ) if $something_went_wrong;
return Result->new( error => 0, ... );
}
my $result = some_sub( ... );
if( $result->is_error ) { ... };
Run Code Online (Sandbox Code Playgroud)
这不涉及全局变量,远距离行动,确定头痛或需要特殊特殊情况.您创建一个小类Result或任何您想要调用它的类来包装返回值,以便您拥有结构化数据而不是没有标识的单个值.再也不知道返回值意味着什么了.这undef是真正的价值还是失败的迹象?如果定义了返回值是否正确,或者它是否为真?你的对象可以告诉你这些事情.并且,您可以使用相同的对象die.如果您已经使用了该对象die并将其用作返回值,则几乎没有什么可以推荐您需要做的额外事情来容忍$@.
我在"返回错误对象而不是抛出异常"中详细讨论了这个问题
但是,我知道你无法帮助其他人做什么,所以你仍然要假装Perl有例外.
ike*_*ami 31
这始终是个人偏好的情况.你比较喜欢哪个
my $rv;
if (!eval { $rv = f(); 1 } ) {
...
}
Run Code Online (Sandbox Code Playgroud)
要么
my $rv = try {
f();
} catch {
...
};
Run Code Online (Sandbox Code Playgroud)
但请记住,后者使用anon subs,因此它会混淆return,以及next类似.尝试:: Tiny的try-catch可能会更加复杂,因为你在catch块和它之外添加了通信通道.
返回异常的最佳情况(最简单)场景是if $rv在没有异常时始终为true.它看起来如下:
my $rv;
if ($rv = eval { f() }) {
...
return;
}
Run Code Online (Sandbox Code Playgroud)
VS
my $rv = try {
f();
} catch {
...
};
if (!$rv) {
return;
}
Run Code Online (Sandbox Code Playgroud)
这就是为什么我会使用TryCatch而不是Try :: Tiny我使用这样的模块.
对Perl的更改只是意味着您可以if ($@)再次执行此操作.换一种说法,
my $rv;
if (!eval { $rv = f(); 1 } ) {
...
}
Run Code Online (Sandbox Code Playgroud)
可以写
my $rv = eval { f() };
if ($@) {
...
}
Run Code Online (Sandbox Code Playgroud)
msz*_*man 10
Try::Tiny简单轻便.太容易了.我们有两个问题:
return的陈述总是存在问题所以我做了一些改动Try::Tiny,这对我们有所帮助.现在我们有:
try sub {},
catch 'SomeException' => sub {},
catch [qw/Exception1 Exception2/] => sub {},
catch_all sub {};
Run Code Online (Sandbox Code Playgroud)
我知道-这个语法是有点异国情调,但由于明显的" sub",我们的程序员现在知道," return"语句只是从异常处理程序退出,我们始终只捕获这个例外,我们要赶上:)