Perl社区的共识似乎是Try::Tiny
是处理异常的首选方式。
Perl 5.14(我使用的版本)seems to solve issues eval
Try::Tiny
地址。 Try::Tiny
还会为我带来任何好处吗?
答案 0 :(得分: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 ) { ... };
这不涉及全球变量,远距离行动,确定头痛或需要特殊特价。您可以创建一个小类Result
,或者您想要调用的任何类,来包装返回值,以便您拥有结构化数据而不是没有标识的单个值。再也不知道返回值意味着什么了。 undef
是真正的价值还是失败的表现?如果定义了返回值是否正确,或者它是否为真?你的对象可以告诉你这些事情。并且,您可以将同一对象与die
一起使用。如果您已经将对象与die
一起使用并将其作为返回值使用,则很少需要推荐所有额外的内容来容忍$@
。
我在"Return error objects instead of throwing exceptions"
中详细讨论了这个问题但是,我知道你无法帮助其他人做什么,所以你仍然要假装Perl有例外。
答案 1 :(得分:30)
这始终是个人偏好的情况。你喜欢
吗?my $rv;
if (!eval { $rv = f(); 1 } ) {
...
}
或
my $rv = try {
f();
} catch {
...
};
但请记住,后者使用anon subs,所以它与return
以及next
等混淆。 Try :: Tiny的try-catch可能会因为你在catch块和它之外添加通信通道而变得更加复杂。
返回异常的最佳情况(最简单)方案是,如果没有异常,$rv
始终为true。它看起来如下:
my $rv;
if ($rv = eval { f() }) {
...
return;
}
VS
my $rv = try {
f();
} catch {
...
};
if (!$rv) {
return;
}
这就是为什么我会使用TryCatch而不是Try::Tiny来使用这样的模块。
对Perl的更改只是意味着您可以再次执行if ($@)
。换句话说,
my $rv;
if (!eval { $rv = f(); 1 } ) {
...
}
可以写
my $rv = eval { f() };
if ($@) {
...
}
答案 2 :(得分:14)
如果没有别的,Try::Tiny
仍然是很好的语法糖。如果你想要一些更重量级的东西,还有TryCatch
,这解决了与Try::Tiny
中的子句是子例程(例如,return
不离开这一事实相关的一些问题封闭功能)。
答案 3 :(得分:10)
Try::Tiny
简单轻便。太容易了。我们有两个问题:
return
'声明的问题所以我对Try::Tiny
进行了一些更改,这对我们有所帮助。现在我们有:
try sub {},
catch 'SomeException' => sub {},
catch [qw/Exception1 Exception2/] => sub {},
catch_all sub {};
我知道 - 这种语法有点奇特,但是由于明显的'sub
',我们的程序员现在知道'return
'语句只是从异常处理程序退出,而我们总是只捕获这个我们想要捕获的异常:)
答案 4 :(得分:0)
要么:
local $@;
eval { … }
...防止$ @的更改影响全局范围,或使用Try :: Tiny。
从语法上讲,有些情况我喜欢其中一种。
答案 5 :(得分:0)
Try :: Tiny很棒,但是在最后一个花括号处需要半冒号,并且不允许使用异常变量赋值,更不用说捕获异常类了。 TryCatch曾经做得很好,但是has been broken with the new version 0.006020中的Devel::Declare却做得很好。另一个很棒的实现是Syntax::Keyword::Try,但是它没有实现异常变量分配或捕获异常类。
有一个新模块Nice::Try,它是一个完美的替代品。
没有必要在最后一个括号上使用半冒号,例如Try :: Tiny。
您也可以像这样进行异常变量分配
try
{
# something
}
catch( $e )
{
# catch this in $e
}
它也可以使用类异常(如
)工作 try
{
# something
}
catch( Exception $e )
{
# catch this in $e
}
它还支持finally
。它的功能集使其非常独特。
完全公开:TryCatch损坏时,我已经开发了此模块。