Есть ли более чистый способ условно «последнего» выхода из этого цикла Perl? - PullRequest
9 голосов
/ 07 сентября 2011

На самом деле не зная Perl, я улучшал скрипт Perl с помощью дружественной поисковой системы.

Я обнаружил, что мне нужно выйти из цикла при установке флага, если условие выполняется:

foreach my $element (@array) {
    if($costlyCondition) {
        $flag = 1;
        last;
    }
}

Я знаю, что лучший способ использовать «последний» - это что-то вроде этого:

foreach my $element (@array) {
    last if ($costlyCondition);
}

Конечно, это означает, что, хотя я могу наслаждаться синтаксическим сахаром, я не могуустановить свой флаг внутри цикла, что означает, что мне нужно еще раз оценить $costlyCondition.

Есть ли более чистый способ сделать это?

Ответы [ 4 ]

21 голосов
/ 07 сентября 2011

Вы можете использовать блок do {...}:

do {$flag = 1; last} if $costlyCondition

Вы можете использовать оператор ,, чтобы присоединиться к операторам:

$flag = 1, last if $costlyCondition;

youможно сделать то же самое с логическим оператором &&:

(($flag = 1) && last) if $costlyCondition;

или даже с более низким приоритетом and:

(($flag = 1) and last) if $costlyCondition;

в конце дня, естьнет реальной причины делать что-либо из этого.Они все делают точно так же, как ваш оригинальный код.Если ваш оригинальный код работает и легко читается, оставьте его как есть.

7 голосов
/ 07 сентября 2011

Я согласен с Натаном, что хотя аккуратный код выглядит аккуратно, иногда читаемая версия лучше. Хотя, черт возьми, вот ужасная версия:

last if $flag = $costly_condition;

Обратите внимание на использование присваивания = вместо равенства ==. Присвоение вернет любое значение в $costly_condition.

Это, конечно, не составит $flag = 1, но что бы $costly_condition не было. Но так как это должно быть правдой, то будет $flag. Чтобы исправить это, вы можете - как сказал Зайд в комментариях - использовать:

last if $flag = !! $costly_condition;

Как уже упоминалось, довольно ужасные решения, но они работают.

5 голосов
/ 07 сентября 2011

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

my $flag = check_elements(\@array);

# later...

sub check_elements {
  my $arrayref = shift;
  for my $ele (@$arrayref) {
    return 1 if $costly_condition;
  }
  return 0;
}
0 голосов
/ 08 сентября 2011

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

foreach my $element (@array) {
    $flag = 1 and last if $costlyCondition;
}
...