Perl 使用Try::Tiny还是Eval?

Perl 使用Try::Tiny还是Eval?,perl,Perl,哪个更安全、更好、更清洁、更推荐使用 我用过: sub insert_exec { my ($self, $c, $args) = @_; my ($params, $table, $model) = $self->_init({context => $c, args => $args}); eval { $model->insert($table, $params); }; if ($@) { return $c->sh

哪个更安全、更好、更清洁、更推荐使用

我用过:

sub insert_exec {
    my ($self, $c, $args) = @_;
    my ($params, $table, $model) = $self->_init({context => $c, args => $args});
    eval {  $model->insert($table, $params);
    };
    if ($@) {  return $c->show_error($@);  } ## error
    $c->redirect("/index");
}
但是对于这种情况(参见错误部分),我被告知使用Try::Tiny更好


我的问题是:您将如何编写此代码?为什么选择这种方式?

不使用
Try::Tiny
可以为您节省额外的依赖性

使用它可以让您在不了解Perl习惯用法的情况下编写可以理解的代码(用业界更常见的术语代替它们)


你需要决定哪些对你更有价值,因为很难客观地衡量它们的相对价值。

更新

多亏了一位匿名用户,我才能够纠正我答案中的一个错误。
catch
块中的
return
没有达到预期效果,因为它只从
catch
子例程返回

如果没有异常,
try
返回
try
块的值,否则返回
catch
块的值。因此,如果插入成功,此版本将正确执行并返回
$c->redirect(“/index”)
,否则它将调用并返回
$c->show\u error($)
的值


这一点非常重要,因为在一般情况下,使用
eval
处理错误确实非常困难。模块的文档说明了这一点

此模块提供了简单的try/catch/finally语句,旨在最大限度地减少eval块的常见错误,而不是其他错误

本模块的主要重点是为那些。。。他们仍然希望在每次没有5行样板的情况下编写正确的评估块

您的代码如下所示

use Try::Tiny;

sub insert_exec {
  my ($self, $c, $args) = @_;
  my ($params, $table, $model) = $self->_init({context => $c, args => $args});
  try {
    $model->insert($table, $params);
  }
  catch {
    return $c->show_error($_);
  };
  $c->redirect("/index");
}
我希望你会同意,这样更好

有两点值得注意:

  • try
    catch
    是被编码为类似于语言单词的子程序。这意味着在最后一个右大括号后面必须加一个分号

  • 出于同样的原因,
    try
    catch
    块中的
    return
    将无法按预期工作,只需退出块,返回到父子例程。见我的更新上面

  • catch
    块中,
    $@
    具有
    try
    之前的原始值。该错误产生的值位于
    $\uu


最好不要依靠
$@
发出错误信号,而只是将其用作错误消息的来源,因此我将其写成:

my $success = eval { $model->insert($table, $params) };
unless ($success) {
    return $c->show_error($@);
}
如果您评估的内容在成功时可能不会返回真实值,那么:

my $success = eval { $model->insert($table, $params); 1 };

当事情变得比这更复杂时,我可能会使用Try::Tiny,例如,函数返回一个您想要保存的值,但可能不是真值(或者甚至可能没有定义),并且您想要捕获异常。

如果匿名用户没有足够的信誉来发布评论试图编辑我的答案,那就更好了,添加此文本。这是一个非常好的观点,我已经做了适当的更新。使用
Try::Tiny
时,结构更好,但与原始帖子有很大不同。在编写时,try和catch块都是子例程,因此catch中的返回仅从匿名sub返回,而不是从
insert\u exec
返回。这意味着在异常情况下也会执行重定向。这是
Try::Tiny
的常见陷阱。
my $success = eval { $model->insert($table, $params); 1 };