使用Perl的eval时常见的陷阱是什么?

与Perl的 eval相关的常见缺陷是什么,这可能会使您选择使用诸如 Try::Tiny的模块?

解决方法

Perl的eval有两种口味,即字符串eval和block eval. String eval调用编译器来执行源代码.块eval包围已经编译的代码,可以捕获模块异常. (string eval也捕获模块异常以及任何编译错误).

Try :: Tiny仅适用于eval的块形式,但以下内容适用于这两种形式.

每次调用eval它都会改变$@的值.如果eval成功或者eval所捕获的错误,它将是“’”

这意味着您随时调用eval,您将清除以前的任何错误消息. Try :: Tiny为您定制$@变量,以便成功的eval不会清除以前失败的eval的消息.

另一个陷阱来自使用$@作为检查来确定eval是否成功.一个常见的模式是:

eval {...};
if ($@) {
   # deal with error here
}

这依赖于两个假设,首先,任何错误消息$@可以包含是一个真实值(通常为true),并且eval块和if语句之间没有代码.

当然,后者是真实的,但是如果eval块创建了一个对象,并且该eval在eval失败后超出了该范围,则该对象的DESTROY方法将在if语句之前被调用.如果DESTROY碰巧调用eval而不本地化$@并且成功,那么在运行if语句的时候,$@变量将被清除.

解决这些问题的方法是:

my $return = do {
    local $@;
    my $ret;
    eval {$ret = this_could_fail(); 1} or die "eval Failed: $@";
    $ret
};

打破这一行逐行,本地$@为do块创建一个新的$@,这阻止了以前的值的颠覆.我的$ret将是评估代码的返回值.在eval块中,$ret被分配给,然后块返回1.这样,无论什么,如果eval成功,它将返回true,如果失败,它将返回false.在失败的情况下,由你自己决定.上面的代码只是死了,但你可以很容易地使用eval块的返回值来决定运行其他代码.

由于上述咒语有点乏味,容易出错.使用像Try :: Tiny这样的模块可以使您免受这些潜在的错误,每个eval都需要多一些函数调用.知道如何正确地使用eval是很重要的,因为如果你必须使用字符串eval,Try :: Tiny不会帮助你.

相关文章

忍不住在 PerlChina 邮件列表中盘点了一下 Perl 里的 Web 应用框架(巧的是 PerlBuzz 最近也有一篇相关...
bless有两个参数:对象的引用、类的名称。 类的名称是一个字符串,代表了类的类型信息,这是理解bless的...
gb2312转Utf的方法: use Encode; my $str = "中文"; $str_cnsoftware = encode("utf-8...
  perl 计算硬盘利用率, 以%来查看硬盘资源是否存在IO消耗cpu资源情况; 部份代码参考了iostat源码;...
1 简单变量 Perl 的 Hello World 是怎么写的呢?请看下面的程序: #!/usr/bin/perl print "Hello W...
本文介绍Perl的Perl的简单语法,包括基本输入输出、分支循环控制结构、函数、常用系统调用和文件操作,...