【问题标题】:Can the Perl compiler tell me if I have an unchecked exception in my code?Perl 编译器能告诉我我的代码中是否有未经检查的异常吗?
【发布时间】:2011-02-13 05:18:51
【问题描述】:

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

编辑:我最感兴趣的是让编译器或 IDE 告诉我我的代码某处有未经检查的异常的方法。

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

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

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

【问题讨论】:

  • 没有,不是真的。有一些近似值和技巧可以到达那里。
  • 这已经在几个问题中讨论过:stackoverflow.com/questions/2439966/…(其他问题请参见那里的相关链接)

标签: perl exception compiler-construction die


【解决方案1】:

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

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

  2. Any 方法可以die,或至少任何非平凡方法。它会调用别的东西,它可能会调用别的东西,等等,所以保证不会抛出异常的唯一方法是追踪(潜在)调用的所有级别,以验证那里没有任何可能@ 987654322@。假设异常总是有可能发生并相应地编码会更加务实。

编辑添加:一般来说,Perl5 和静态代码分析并不能很好地配合。我的理解是,这是在 Perl6 中重新设计语言背后的动机之一,所以你可能会有更好的运气。

【讨论】:

  • 感谢您确认没有(非平凡的)编程方式对其进行标记。我在考虑注释或类似的东西,但是您在 2. 中的最后一句话提供了一种更好的做法,恕我直言 - 无法开始对每个现有库进行注释。
【解决方案2】:

没有见过这样的事情,但也许子例程属性可能会影响您的工作?

这是一个使用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

也许PPIPerl::Critic 和/或Padre 的(混合)可以适应使用这样的东西?

/I3az/

【讨论】:

  • 好主意,但是呃。属性::处理程序。 :) 我说的是在他的 CPAN 目录中拥有该模块最新版本的那个人。
【解决方案3】:

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

另外,请参阅Object Oriented Exception Handling in Perl

【讨论】:

  • @Konerak:“未经检查的”异常并不邪恶。有时你需要做的就是死,而且没有必然的理由需要抓住它。
【解决方案4】:

来自文档“Exceptions

  1. $@ 没有告诉我们错误发生在哪里

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

    子抛出{ 我的 $mess = join('', @_); $混乱 =~ s/\n?$/\n/; 我的 $i = 1; 本地 $" = "', '"; 包数据库; 而(我的@parts = 调用者($i++)){ 我的 $q; $q = "'" 如果@DB::args; $mess .= " -> $parts3" 。 " 在 $parts1 行 $parts2\n"; } 死 $mess; }

这样,您还可以从“CPAN”和“Object Oriented Exception Handling in Perl”获取引用

【讨论】:

  • 请请,请添加评论以投反对票。我想知道我误解了什么。
  • 我不是反对者,但我怀疑你被反对的原因是 OP 询问“我如何确定给定方法的定义的行为集是否包括它可能抛出的可能性例外”,而您的回答没有解决这个问题。
  • 谢谢戴夫,非常感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
  • 2011-01-13
  • 2010-09-09
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
相关资源
最近更新 更多