Может ли компилятор Perl сказать мне, есть ли в моем коде непроверенное исключение?

Есть ли в Perl способ объявить, что метод может выдать ошибку (или умереть)?

РЕДАКТИРОВАТЬ: Меня больше всего интересует способ заставить компилятор или IDE сказать мне, что где-то в моем коде есть непроверенное исключение.

Мне всегда нравилось, как в Java метод может обрабатывать исключение и / или выдавать его. Сигнатура метода позволяет помещать «выбрасывает MyException», поэтому хорошая среда IDE / компилятор будет знать, что если вы используете указанный метод где-то в своем коде, вам придется проверить исключение или объявить, что ваша функция «выбрасывает» исключение дальше. .

Я не могу найти что-то подобное в Perl. Мой коллега написал метод, который «умирает» при неправильном вводе, но я забываю eval-if ($ @) it ..., конечно, ошибка была обнаружена только тогда, когда пользователь запускал приложение.

(конечно, я сомневаюсь, что существует какая-либо существующая среда IDE, которая могла бы найти такие вещи для Perl, но по крайней мере perl -cw должен быть в состоянии, нет?)


person Konerak    schedule 28.04.2010    source источник
comment
Нет, на самом деле нет. Есть приближения и уловки, чтобы туда добраться.   -  person Paul Nathan    schedule 28.04.2010
comment
Это уже обсуждалось в нескольких вопросах: stackoverflow.com/questions/2439966/ (и просмотрите соответствующие ссылки для остальных)   -  person Ether    schedule 28.04.2010


Ответы (4)


Два возможных ответа. Выберите то, что вам больше нравится:

  1. В Perl на это указывает POD модуля. Программно пометить это невозможно, поэтому вместо этого вам нужно полагаться на документацию.

  2. Любой метод может die или, по крайней мере, любой нетривиальный метод. Он будет вызывать что-то еще, что, вероятно, вызывает что-то еще и т. Д., Поэтому единственный способ гарантировать, что исключение не будет создано, - это проследить все уровни (потенциальных) вызовов, чтобы убедиться, что там нет ничего, что могло бы die . Гораздо более прагматично предположить, что исключения всегда возможны, и кодировать соответственно.

Отредактировано для добавления. Как правило, Perl5 и статический анализ кода не очень хорошо уживаются. Насколько я понимаю, это одна из причин редизайна языка Perl6, так что, возможно, вам повезет больше.

person Dave Sherohman    schedule 28.04.2010
comment
Спасибо, что подтвердили, что нет (нетривиального) программного способа пометить его. Я думал об аннотациях или что-то в этом роде, но ваше последнее предложение в 2. предлагает лучшую практику, ИМХО - нельзя начинать аннотировать каждую существующую библиотеку. - person Konerak; 28.04.2010

Ничего подобного не видел, но, может быть, вам помогут атрибуты подпрограммы?

Вот небольшое подтверждение концепции с использованием 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

Возможно (смесь) PPI, _ 5_ и / или _ 6_ можно приспособить для использования чего-то подобного?

/I3az/

person draegtun    schedule 28.04.2010
comment
Хорошая идея, но уууу. Атрибут :: Обработчики. :) И я говорю это как парень с самым последним выпуском указанного модуля в его каталоге CPAN. - person tsee; 28.04.2010


из документа "Исключения"

  1. $ @ не сообщает нам, где произошла ошибка

  2. Мы можем обойти это с помощью специальной функции:

    подбросить {мой $ mess = join ('', @_); $ mess = ~ s / \ n? $ / \ n /; мой $ i = 1; local $ "=" ',' "; пакет DB; while (my @parts = caller ($ i ++)) {my $ q; $ q =" '"if @DB :: args; $ mess. =" -> $ parts3 "." в $ parts 1 строка $ parts 2 \ n ";} die $ mess;}

При этом вы также можете брать ссылки из "CPAN" и "Объектно-ориентированная обработка исключений в Perl"

person Space    schedule 28.04.2010
comment
Пожалуйста, оставьте комментарий для отрицательного голоса. Я хочу знать, что я неправильно понял. - person Space; 28.04.2010
comment
Я не голосующий против, но я подозреваю, что причина, по которой вы получили отрицательное голосование, заключается в том, что OP спросил, как я могу определить, включает ли определенный набор поведений данного метода возможность того, что он может вызвать исключение, и ваш ответ не касается этого вопроса . - person Dave Sherohman; 28.04.2010
comment
Спасибо, Дэйв, очень ценю твой ответ. - person Space; 28.04.2010