2014-09-12 4 views
7

У меня есть программа с циклом while, которая имеет несколько точек, где определенные условия требуют принятия какого-либо действия, а затем пропустить оставшуюся часть итерации.Завершение итерации цикла из подпрограммы

Поскольку это всегда будет тот же код, я хотел бы поместить его в подпрограмму, но когда я попробую использовать 'next;' в качестве заключительного заявления в подпункте я получаю предупреждение (Выход из подпрограммы через следующий в ...), хотя он работает так, как предполагалось.

т.е. без суб:

while (#condition) { 

    ## do stuff 

    if (#condition to skip iteration) { 
     ## action 
     next; 
    } 

    ## do more stuff, with the above block repeated several times 
} 

с суб:

while (#condition) { 

    ## do stuff 

    &skip if (#condition to skip iteration); 

    ## do more stuff, with more calls to &skip 
} 

sub skip() { 
    ## action 
    next; 
} 

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

Мой вопрос:

  • Пользуется 'рядом;' в подпрограмме таким образом нормально, или это опасная/плохая практика?
  • Есть ли лучший способ пропустить остальную итерацию из подпрограммы?
  • Если это нормально, и нет лучшего способа, есть ли способ подавить предупреждение?

ответ

4

Ваш предупреждающий инстинкт, вероятно, прав. Как вы говорите, next просто не является заявлением, которое входит в подпрограмму. Даже если вы не предпочитаете его, это почти наверняка лучше:

while (#condition) { 

    ## do stuff 

    &skip, next if (#condition to skip iteration); 

    ## do more stuff, with more calls to &skip 
} 

sub skip() { 
    ## action 
} 

(я посчастливилось иметь достаточно спокойное отношение к нестандартным методам программирования, особенно если они не злоупотребляют Если вы сильно о вложении next. в этом случае я не буду спорить с вами, так как это ваша программа. Тем не менее, поскольку вы спросили совета, я согласен с вашим инстинктом в том, что встраивание next, вероятно, не очень хорошая идея.)

+0

Зачем использовать круглые кронштейны на субпробеге? Нет необходимости использовать прототипирование или подписи здесь. Может быть, менее запутанно удалить их. – jmmeier

3

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

use warnings; 

sub foo { 
    print ($_, "\n"); 
} 

for (1..10) { 
    foo(), next if $_ %2;; 
} 
6

С Изучаем Perl шестого издания страницу 179 (сноска)

Это, вероятно, не хорошая идея, но вы можете использовать эти операторы loop-control изнутри подпрограммы для управления циклом, который находится вне подпрограммы. То есть, если подпрограмма вызывается в блоке цикла, , и подпрограмма выполняется последним, когда в подпрограмме нет цикла цикла , поток управления будет прыгать сразу после блока цикла в основном коде. Эта возможность использования управления контуром от в рамках подпрограммы может уйти в будущей версии Perl, и без , вероятно, пропустит ее.

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

use strict; 
use warnings; 

while(<>) { 
    chomp; 
    maybeskip($_) && next if m/2/; #maybe skip if match 2 
    print "$_\n"; 
} 

sub maybeskip { 
    $_[0] !~ m/0/; #skip only if not match 0 
    # the sub retuns the result of the last executed expression 
    # if this is not wanted you should use explicit return $value; 
} 

для

seq 25 | perl script 

принтами:

1 
3 
4 
5 
6 
7 
8 
9 
10 
11 
13 
14 
15 
16 
17 
18 
19 
20 

например пропущено все совпадения 2, но не 20

8

Легко подавить предупреждение. Просто поместите следующую строку выше вашего next:

no warnings "exiting"; 

Предупреждение там по причине - с помощью next в хелперов к югу, как это может быть запутанным для следующего человека, который должен прочитать код (который может быть вы через 6 месяцев!), потому что next не происходит лексически в блоке цикла. Если вы просто читаете блок цикла, вы можете не заметить, что next дальше по файлу; и если вы просто читаете определение подпрограммы, вы можете быть не уверены, для чего это next. Вам нужно прочитать обе части кода вместе, чтобы понять это. Это делает его более запутанным, чем использование next непосредственно внутри цикла.

Кроме того, это ограничивает повторную калибровку skip() sub, которую вы только что определили. Хотите повторно использовать этот skip() в другом цикле? Вы должны надеяться, что логика пропусков все еще имеет смысл в новом цикле.

Если вы все это рассмотрели и хотите продолжить, просто отключите предупреждение, как я показал выше. Предупреждения - это не ошибки, а просто предупреждения. Вот почему предупреждения называются «предупреждениями». Они предназначены, чтобы обратить ваше внимание на что-то потенциально проблематично; не мешать вам делать то, что вы решили, полезно.

3

Вы можете поместить часть/все условия проскальзывания внутри подпрограммы, возвращая правку до next и ложно продолжать работать с помощью оператора and.

while (#condition) { 

    ## do stuff 

    &skip and next if (#condition to skip iteration); 

    ## or like this 
    next if (#condition to skip iteration) and &skip; 

    ## or like this 
    (#condition to skip iteration) and &skip and next; 

    ## do more stuff, with more calls to &skip 
} 

sub skip() { 
    ## action 
    return $common_skip_condition; 
} 
Смежные вопросы