Perl 中的异常有什么问题? [英] What's broken about exceptions in Perl?

查看:27
本文介绍了Perl 中的异常有什么问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

另一个问题中的讨论让我想知道:其他编程语言的异常系统有哪些 Perl 所没有的?

A discussion in another question got me wondering: what do other programming languages' exception systems have that Perl's lacks?

Perl 的内置异常有点ad-hoc,因为它们像 Perl 5 对象系统一样,在某种程度上是事后附加的,并且它们重载了其他关键字(evaldie),它们不是专门用于异常的.

Perl's built-in exceptions are a bit ad-hoc in that they were, like the Perl 5 object system, sort-of bolted on as an afterthought, and they overload other keywords (eval and die) which are not dedicated specifically to exceptions.

与具有内置 try/throw/catch 类型语法的语言相比,语法可能有点难看.我通常是这样做的:

The syntax can be a little ugly, compared to languages with builtin try/throw/catch type syntax. I usually do it like this:

eval { 
    do_something_that_might_barf();
};

if ( my $err = $@ ) { 
    # handle $err here
}

有几个 CPAN 模块提供语法糖来添加 try/catch 关键字并允许轻松声明异常类层次结构等.

There are several CPAN modules that provide syntactic sugar to add try/catch keywords and to allow the easy declaration of exception class hierarchies and whatnot.

我看到的 Perl 异常系统的主要问题是使用特殊的全局 $@ 来保存当前错误,而不是使用专用的 catch 类型机制从范围的角度来看,可能更安全,尽管我个人从未遇到过 $@ 被修改的任何问题.

The main problem I see with Perl's exception system is the use of the special global $@ to hold the current error, rather than a dedicated catch-type mechanism that might be safer, from a scope perspective, though I've never personally run into any problems with $@ getting munged.

推荐答案

一些异常类,例如错误,无法从 try/catch 块中处理流控制.这会导致细微的错误:

Some exception classes, e.g. Error, cannot handle flow control from within try/catch blocks. This leads to subtle errors:

use strict; use warnings;
use Error qw(:try);

foreach my $blah (@somelist)
{
    try
    {
        somemethod($blah);
    }
    catch Error with
    {
        my $exception = shift;
        warn "error while processing $blah: " . $exception->stacktrace();
        next;    # bzzt, this will not do what you want it to!!!
    };

    # do more stuff...
}

解决方法是使用状态变量并在 try/catch 块之外检查它,在我看来,它看起来非常像糟糕的 n00b 代码.

The workaround is to use a state variable and check that outside the try/catch block, which to me looks horribly like stinky n00b code.

错误中的另外两个陷阱"(这两个都让我感到悲伤,因为如果您以前没有遇到过它们,调试起来很糟糕):

Two other "gotchas" in Error (both of which have caused me grief as they are horrible to debug if you haven't run into this before):

use strict; use warnings;
try
{
    # do something
}
catch Error with
{
    # handle the exception
}

看起来很明智,对吧?这段代码可以编译,但会导致奇怪和不可预测的错误.问题是:

Looks sensible, right? This code compiles, but leads to bizarre and unpredictable errors. The problems are:

  1. use Error qw(:try) 被省略,因此 try {}... 块将被错误解析(您可能会也可能不会看到警告,具体取决于在您的其余代码中)
  2. catch 块后缺少分号!不直观,因为控制块不使用分号,但实际上 try 是一个原型方法调用.
  1. use Error qw(:try) was omitted, so the try {}... block will be misparsed (you may or may not see a warning, depending on the rest of your code)
  2. missing semicolon after the catch block! Unintuitive as control blocks do not use semicolons, but in fact try is a prototyped method call.

哦是的,这也提醒我,因为 trycatch 等是方法调用,这意味着这些块中的调用堆栈不会是你所期望的.(实际上有两个额外的堆栈级别,因为 Error.pm 中的内部调用.)因此,我有几个模块充满了这样的样板代码,这只会增加混乱:

Oh yeah, that also reminds me that because try, catch etc are method calls, that means that the call stack within those blocks will not be what you expect. (There's actually two extra stack levels because of an internal call inside Error.pm.) Consequently, I have a few modules full of boilerplate code like this, which just adds clutter:

my $errorString;
try
{
    $x->do_something();
    if ($x->failure())
    {
        $errorString = 'some diagnostic string';
        return;     # break out of try block
    }

    do_more_stuff();
}
catch Error with
{
    my $exception = shift;
    $errorString = $exception->text();
}
finally
{
    local $Carp::CarpLevel += 2;
    croak "Could not perform action blah on " . $x->name() . ": " . $errorString if $errorString;
};

这篇关于Perl 中的异常有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆