Perl 编译器可以告诉我代码中是否存在未经检查的异常吗?

发布于 2024-08-31 05:44:51 字数 421 浏览 5 评论 0原文

Perl 中有没有办法声明一个方法可以抛出错误(或死亡)?

编辑: 我最感兴趣的是获取编译器或 IDE 的方法告诉我我的代码中有一个未经检查的异常。

我一直很喜欢 Java 中的方法如何处理异常和/或抛出异常。方法签名允许放置“抛出 MyException”,因此一个好的 IDE/编译器会知道,如果您在代码中的某个位置使用所述方法,则必须检查异常或声明您的函数以进一步“抛出”异常。

我在 Perl 中找不到类似的东西。我的一位同事编写了一种方法,该方法会因输入错误而“死亡”,但我忘记了 eval-if($@) 它......当然,只有在用户运行应用程序时才发现该错误。

(当然我怀疑是否有任何现有的 IDE 可以为 Perl 找到这些东西,但至少 perl -cw 应该能够,不是吗?)

Is there a way in Perl to declare that a method can throw an error (or die)?

EDIT: What interests me the most is a way to get the compiler or IDE to tell me I have an unchecked exception somewhere in my code.

I always loved how in Java, a method could handle an Exception and/or throw it. The method signature allows to put "throws MyException", so a good IDE/compiler would know that if you use said method somewhere in your code, you'd have to check for the Exception or declare your function to "throws" the Exception further.

I'm unable to find something alike in Perl. A collegue of mine wrote a method which "dies" on incorrect input, but I forget to eval-if($@) it... offcourse the error was only discovered while a user was running the application.

(offcourse I doubt if there is any existing IDE that could find these kind of things for Perl, but atleast perl -cw should be able to, no?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

上课铃就是安魂曲 2024-09-07 05:44:51

两个可能的答案。选择您更喜欢的:

  1. 在 Perl 中,这由模块的 POD 指示。无法以编程方式标记它,因此您需要依赖文档。

  2. 任何方法都可能消亡,或者至少是任何不平凡的方法。它将调用其他东西,这可能会调用其他东西,等等,因此保证不会抛出异常的唯一方法是跟踪(潜在)调用的所有级别以验证是否没有任何可能<代码>死亡。更务实的是,假设异常总是可能发生并相应地编写代码。

编辑添加:作为一般规则,Perl5 和静态代码分析并没有真正相处得那么好。我的理解是,这是 Perl6 语言重新设计背后的动机之一,所以你可能会有更好的运气。

Two potential answers. Pick whichever you like better:

  1. In Perl, this is indicated by the module's POD. There's no way of marking it programmatically, so you need to rely on the documentation instead.

  2. Any method can die, or at least any nontrivial method. It's going to call something else, which probably calls something else, etc., so the only way to guarantee that no exception will be thrown is to trace down through all the levels of (potential) calls to verify that there's nothing there that might die. Much more pragmatic to just assume that exceptions are always a possibility and code accordingly.

Edited to add: As a general rule, Perl5 and static code analysis don't really get along all that well. My understanding is that this is one of the motivations behind the language redesign in Perl6, so you may have better luck there.

榆西 2024-09-07 05:44:51

没有见过这样的东西,但也许子例程属性可能会帮助你?

这是一个使用 Attribute: 的小型概念证明处理程序

ThrowsExceptionHandler.pm

package ThrowsExceptionHandler;
use Modern::Perl;
use Attribute::Handlers;

our @subs;

sub ThrowsException :ATTR(CODE) {
    push @subs, {
        package  => $_[0],
        symbol   => $_[1],
        subname  => *{$_[1]}{NAME},
        referent => $_[2],
        attr     => $_[3],
        data     => $_[4],
        phase    => $_[5],
        filename => $_[6],
        linenum  => $_[7],
    };
}

sub does_throw {
    my ($class, $subname) = @_;
    (grep { $_->{subname} eq $subname } @subs) ? 1 : 0;
}

1;

example.pl

use Modern::Perl;
use base qw(ThrowsExceptionHandler);

sub baz :ThrowsException {
    die "Throws error";
}

sub foo {
    warn "warning only";
}


say ThrowsExceptionHandler->does_throw( 'baz' );  # => 1
say ThrowsExceptionHandler->does_throw( 'foo' );  # => 0

也许(混合)PPI, Perl::Critic 和/或 < code>Padre 可以改编成使用这样的东西吗?

/I3az/

Not seen anything like this but perhaps subroutine attributes may get your part of the way?

Here is a small proof of concept using Attribute::Handlers

ThrowsExceptionHandler.pm

package ThrowsExceptionHandler;
use Modern::Perl;
use Attribute::Handlers;

our @subs;

sub ThrowsException :ATTR(CODE) {
    push @subs, {
        package  => $_[0],
        symbol   => $_[1],
        subname  => *{$_[1]}{NAME},
        referent => $_[2],
        attr     => $_[3],
        data     => $_[4],
        phase    => $_[5],
        filename => $_[6],
        linenum  => $_[7],
    };
}

sub does_throw {
    my ($class, $subname) = @_;
    (grep { $_->{subname} eq $subname } @subs) ? 1 : 0;
}

1;

example.pl

use Modern::Perl;
use base qw(ThrowsExceptionHandler);

sub baz :ThrowsException {
    die "Throws error";
}

sub foo {
    warn "warning only";
}


say ThrowsExceptionHandler->does_throw( 'baz' );  # => 1
say ThrowsExceptionHandler->does_throw( 'foo' );  # => 0

Perhaps (a mixture of) PPI, Perl::Critic and/or Padre can be adapted to use something like this?

/I3az/

昔梦 2024-09-07 05:44:51

您检查过 CPAN 吗? Error::TryCatch 是一种选择, Exception::Class 是另一个等等。

另请参阅 面向对象Perl 中的异常处理

Have you checked CPAN? Error::TryCatch is one option, Exception::Class is another, etc. etc.

Also, see Object Oriented Exception Handling in Perl.

忆梦 2024-09-07 05:44:51

来自文档“例外

  1. $@ 不告诉错误发生的位置

  2. 我们可以使用自定义函数来解决这个问题:

    子抛出{
    我的 $mess = join('', @_);
    $mess =~ s/\n?$/\n/;
    我的 $i = 1;
    本地 $" = "', '";
    包数据库;
    while (我的@parts = 来电者($i++)) {
    我的$q; $q = "'" if @DB::args;
    $mess .= " -> $parts3" .
    " 在 $parts1 行 $parts2\n";
    }
    死$混乱;
    我们可以使用自定义函数来

您还可以从“CPAN”和“Perl 中面向对象的异常处理"

from document "Exceptions"

  1. $@ doesn't tell us where the error occurred

  2. We can get around this with a custom function:

    sub throw {
    my $mess = join('', @_);
    $mess =~ s/\n?$/\n/;
    my $i = 1;
    local $" = "', '";
    package DB;
    while (my @parts = caller($i++)) {
    my $q; $q = "'" if @DB::args;
    $mess .= " -> $parts3" .
    " at $parts1 line $parts2\n";
    }
    die $mess;
    }

With that you can also take references from "CPAN" and "Object Oriented Exception Handling in Perl"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文