Menu

Циклы while в R: while, repeat и break

Как работают циклы while в R — проверка условия в начале, repeat с break как аналог do-while, next и привычки, которые уберегают от бесконечных циклов.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Цикл while

Цикл while в R выполняет своё тело, пока условие остаётся TRUE. Там, где цикл for выполняется по одному разу на элемент чего-либо, while выполняется неизвестное число раз — пока не изменится условие:

Каждый цикл while работает благодаря трём частям, и все три здесь видны:

  1. Подготовка перед цикломcount <- 1 даёт условию то, что можно проверить.
  2. Условиеcount <= 5, построенное из обычных операторов сравнения, проверяется перед каждым проходом.
  3. Обновление внутри телаcount <- count + 1 двигает цикл к остановке.

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

Условие проверяется перед каждым проходом

while сначала проверяет условие, а потом выполняет тело. Отсюда два следствия. Если условие уже ложно на старте, тело выполняется ноль раз:

И проверка происходит между полными проходами, а не посреди тела: раз проход начался, он выполняется до конца, даже если условие стало FALSE на полпути. Если нужно выйти посреди тела, для этого есть break (ниже).

Разобранный пример: деление пополам до порога

Естественный дом для while — это «продолжать, пока не»: заранее нельзя знать, сколько потребуется проходов, поэтому for не подходит. Сколько раз можно поделить 1000 пополам, прежде чем результат станет меньше 1?

Десять делений, финал примерно 0.977. Этот шаблон — переменная состояния, которую тело уменьшает, и счётчик, который оно наращивает, — покрывает огромную долю реальных циклов while: численные методы, работающие до достаточно малой погрешности; симуляции, идущие до исчерпания ресурса; повторные попытки, продолжающиеся до успешного вызова.

repeat + break: аналог do-while в R

В R нет ключевого слова do-while — нет цикла, проверяющего условие после тела. Зато есть repeat, который крутится безусловно и вечно, и break, который немедленно выходит из любого цикла. Поставьте проверку с break в конце тела repeat — и вы построили ровно do-while, цикл, чьё тело гарантированно выполнится хотя бы раз:

Тело всегда выполняется до первой проверки, поэтому n удваивается минимум один раз; цикл выходит на 128 — первом удвоении, превысившем 100. Используйте эту форму, когда честное описание звучит как «сделай, а потом реши, делать ли снова»: чтение ввода до корректного, генерация выборок до подходящей. repeat без достижимого break — бесконечный цикл по построению, так что пишите сначала break, а потом заполняйте тело.

break работает одинаково в циклах while и for — это общий выход «здесь мы закончили», и он естественно сочетается с конструкциями if, проверяющими условие посреди тела.

next внутри цикла while

next пропускает остаток текущего прохода и возвращается к проверке условия. В while он работает так же, как в for, — с одной специфичной для while ловушкой: если шаг обновления идёт после next, то его пропуск означает, что переменная цикла никогда не двигается, и вы построили бесконечный цикл. Ставьте обновление перед next:

Это печатает чётные числа с 2 по 10. Переместите i <- i + 1 ниже строки с next — и первое же нечётное значение навсегда пропустит обновление. В циклах for такой опасности нет (переменная цикла продвигается автоматически), что ещё раз говорит в пользу for, когда вы просто идёте по последовательности.

Защита от бесконечных циклов

Любой бесконечный цикл — это один и тот же баг: ничто в теле не меняет переменные, от которых зависит условие, — или меняет их не в ту сторону. В интерактивном режиме можно прервать через Esc или Ctrl+C, но в скрипте процесс просто зависает. Предотвращают это две привычки.

Во-первых, написав условие, сразу спросите себя: «какая строка тела двигает его к FALSE?» — и убедитесь, что эта строка выполняется на каждом пути через тело (помните ловушку с next выше).

Во-вторых, для циклов, чьё завершение трудно доказать, добавляйте ограничитель числа итераций, чтобы ошибка в логике давала диагностируемый результат, а не зависшую сессию. Здесь он защищает цикл в духе Коллатца — многократно делить чётные числа пополам и превращать нечётное x в 3 * x + 1, пока не дойдём до 1:

Стартуя с 10, цикл достигает 1 за 6 шагов. Если бы какое-то начальное значение никогда не доходило до 1, оговорка steps < 10000 всё равно завершила бы цикл, а напечатанное состояние подсказало бы, что что-то пошло не так, — видимый неверный ответ лучше программы, которая не отвечает никогда. Здесь уместен именно сокращённый &&: обе стороны — одиночные значения, и защита читается как одно предложение.

while против for: как выбрать

Правило большого пальца — о том, что вы знаете заранее:

  • Вы знаете, что перебираете (элементы вектора, числа от 1 до n): используйте цикл for — переменная цикла управляет собой сама.
  • Вы знаете только условие остановки (до сходимости, до порога, до корректного значения): используйте while.
  • Тело должно выполниться хотя бы раз, прежде чем проверка обретёт смысл: используйте repeat с завершающим break.

Если вы ловите себя на том, что вручную ведёте счётчик в while только ради обхода вектора, — это переодетый цикл for, переходите на него.

Что вы уносите с собой

  • while (condition) { ... } сначала проверяет, потом выполняет — ложное условие на старте означает ноль проходов.
  • Тело должно двигать условие к FALSE; тройка «подготовка / условие / обновление» — вся дисциплина целиком.
  • В R нет ключевого слова do-while: идиома — repeat { body; if (done) break }, гарантирующая хотя бы один проход.
  • break выходит из любого цикла; при использовании next в while обновляйте переменную цикла до пропуска, иначе она никогда не продвинется.
  • Ограничитель числа итераций (&& steps < 10000) превращает потенциальное зависание в видимый и отлаживаемый неверный ответ.

Дальше: векторы — структура данных, по которой ходили все циклы на этой странице, и причина, по которой многие циклы в R могут исчезнуть совсем.

Часто задаваемые вопросы

Как работает цикл while в R?

while (condition) { ... } сначала проверяет условие и выполняет тело, только пока оно остаётся TRUE. Что-то в теле должно рано или поздно сделать условие FALSE — обычно обновление счётчика или уменьшение значения, — иначе цикл никогда не завершится. Если условие ложно с самого начала, тело выполняется ноль раз.

Есть ли в R цикл do-while?

Как ключевого слова — нет. Идиома такова: repeat { ...body...; if (condition) break }repeat крутится безусловно, поэтому тело гарантированно выполняется хотя бы раз, а break в конце играет роль проверки выхода из do-while.

Как остановить бесконечный цикл в R?

В интерактивном режиме нажмите Esc (RStudio) или Ctrl+C (терминал), чтобы прервать выполнение. Чтобы вообще его не допустить: убедитесь, что тело обновляет переменные из условия на каждом проходе, и добавьте ограничитель числа итераций — while (working && steps < 10000), — чтобы ошибка в логике давала неверный результат, а не зависшую сессию.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ