Try :: Tiny仍然建议在Perl 5.14或更高版本中进行异常处理吗?

时间:2012-04-28 15:34:26

标签: perl exception-handling

Perl社区的共识似乎是Try::Tiny是处理异常的首选方式。

Perl 5.14(我使用的版本)seems to solve issues eval Try::Tiny地址。 Try::Tiny还会为我带来任何好处吗?

6 个答案:

答案 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损坏时,我已经开发了此模块。