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

查看:133
本文介绍了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的对象系统一样,被排除在一个事后,他们重载其他关键字( eval die ),它们不专门用于异常。

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关键字,并允许轻松声明异常类层次结构和whatnot。

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. 使用错误qw(:try)被省略 try {} ... 块将被误解(您可能看不到或可能看不到警告,具体取决于您的其他代码)

  2. 抓取块后的分号丢失!不直观的控件块不使用分号,但事实上尝试是一种原型方法调用
  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.

哦,这也让我想起,因为尝试 catch 等等是方法调用,这意味着这些块中的调用堆栈不会是你期望的。 (实际上有两个额外的堆栈级别,因为内部调用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天全站免登陆