Какой самый элегантный способ поймать сигнал в Perl? - PullRequest
3 голосов
/ 28 мая 2011

У меня есть две строки рядом друг с другом в сценарии Perl, который может выдать __WARN__. Если первый выбрасывает, то я хочу просто вернуться из функции и не пытаться продолжить.

Я знаю, как настроить обработчик перед обеими строками, чтобы я мог сообщить об ошибке и т. Д .:

local $SIG{__WARN__} = sub {
  my $e = shift;
  # log the error etc.
  return;
};
# possibly warning-resulting line 1
# possibly warning-resulting line 2

Но тогда это происходит для обеих линий. Я бы предпочел, чтобы он просто перехватил первый экземпляр и вернулся из функции. Но возвращение в этом обработчике возвращает только обработчик, а не внешнюю функцию.

Есть ли способ возврата из функции при обработке сигнала?

Ответы [ 4 ]

2 голосов
/ 28 мая 2011

Оберните две строки в отдельные функции, и первая из них вернет статус, указывающий, что вызывающая функция должна вернуться. Отдельные функции могут обрабатывать предупреждения по мере необходимости, возможно, используя одну и ту же функцию для ведения одной и той же регистрации.

sub wrap_line_1
{
    local $SIG{__WARN__} = ...;
    ...do line 1...
    return ($warning_fired ? 1 : 0);
}

sub wrap_line_2
{
    local $SIG{__WARN__} = ...;
    ...do line 2...
    return;
}


...calling code...
wrap_line_1() and return;
wrap_line_2();
...
1 голос
/ 28 мая 2011

Нет, вы не можете заставить звонящего вернуться.(Ну, я уверен, что вы можете, с правильным заклинанием черной магии XS. Но не делайте этого!)

Это похоже на ошибочный дизайн;предупреждения не должны быть фатальными ошибками и, конечно, не должны использоваться таким образом.

0 голосов
/ 28 мая 2011

Вы можете умереть () в своем обработчике и поймать его в eval, как показано ниже:

use 5.12.0;

local $SIG{__WARN__} = sub {
  my $e = shift;
  # log the error etc.
  die "$e";
};

func(undef);
func('honk');

sub func {
    my $foo = shift;

    eval {
       my $bar = "a $foo";
       say "$bar";
    };
    if ($@) {
       die $@ unless $@ =~ /^Use of uninitialized value/;
    }
    return;
}

Вы, вероятно, хотите проверить напрямую, может ли появиться предупреждение, и просто вернуть:

sub func {
  my $foo = shift;
  return unless defined($foo);
  ...; # use $foo fine
}
0 голосов
/ 28 мая 2011

Просто сгенерируйте исключение, перехватите и верните в вызывающем объекте.

Заставьте обработчик возвращать значение и проверяйте его для возврата в операторе if после eval.

Фактически выдаже не нужно возвращать значение из обработчика, потому что он не решает, возвращать ли - вы всегда возвращаете, когда ловите.

В частности:

# We're in the caller now
eval{
    local $SIG{__WARN__} = sub {
        my $e = shift;
        # log the error etc.
        die MyWarnException->new("This is an exception.");
    };

    # Offending statements go here
    do_things();

};
if( $@ && $@->isa('MyWarnException')){
    return;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...