Perl中的异常有什么问题? [英] What's broken about exceptions in 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:
-
使用错误qw(:try)
被省略try {} ...
块将被误解(您可能看不到或可能看不到警告,具体取决于您的其他代码)
抓取块后的分号丢失!不直观的控件块不使用分号,但事实上
尝试
是一种原型方法调用。 use Error qw(:try)
was omitted, so thetry {}...
block will be misparsed (you may or may not see a warning, depending on the rest of your code)- 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屋!