Menu

Zero While Loops: итерация в agent-first языке

Как сегодня работают циклы while в Zero: условие, тело цикла, отсутствие for и do-while в раннем языке и какое отношение циклы имеют к явным эффектам.

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

Основы

while выполняет своё тело, пока условие типа bool остаётся true:

while condition {
    // тело
}

Компилятор вычисляет условие перед каждой итерацией:

  • true — выполнить тело, потом проверить снова.
  • false — выйти из цикла.

Тривиальная иллюстрация из примеров Zero, с условием, которое уже false:

Запустите — сработает только второй write. Тело while ни разу не выполнится, потому что условие было false в момент первой проверки.

Условие — это bool

Как и в if/else, условие цикла должно быть bool. Zero не приводит целые, строки или другие значения к булеву.

while count {              // compile error
    // ...
}

while count > 0 {          // ОК
    // ...
}

Условие может быть чем угодно, что вычисляется в bool: привязкой, сравнением, комбинацией &&/|| или вызовом функции. Те же правила, что и у if.

Counted-циклы

Классический паттерн «сделать что-то N раз» использует счётчик и while:

let mut i = 0
while i < 10 {
    // делаем работу
    i = i + 1
}

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

Заметка про mut выше: как именно Zero пишет изменяемые привязки в вашем тулчейне, может отличаться в pre-1.0 версиях. Запустите zero check --json против небольшого теста, чтобы убедиться в точном синтаксисе, который принимает ваш компилятор. Концептуальный паттерн (счётчик + условие + обновление) — стабильная часть.

Бесконечные циклы

while, условие которого всегда true, выполняется вечно:

while true {
    // ждём работу, обрабатываем её, повторяем
}

Это правильная форма для event-loop, REPL или долгоживущего сервера. Чтобы выйти, либо завершите процесс, либо выбросите ошибку из тела, либо переструктурируйте, чтобы условие сломалось.

Когда тянуться к циклу

Циклы — инструмент, к которому стоит тянуться экономно. То, что выглядит как цикл в других языках, в Zero часто имеет более чистую форму:

  • Итерация по фиксированной коллекции: предпочитайте функцию, которую выставляет стандартная библиотека или ваш shape — forEach-помощник, фолдер или рекурсивный обход.
  • Чтение до конца ввода: циклите по fallible-чтению, но используйте check и raises, чтобы аккуратно обработать границу, а не вкладывать флаги состояния.
  • Polling условия: подумайте, не должен ли дизайн вместо этого дать вам сигнал. Polling-циклы — это запах в любом системном языке.

Тот же инстинкт применим и к агентам: плотная декларативная форма легче для рассуждения, чем рукописный счётный цикл, — и для людей, и для генераторов кода.

Циклы и эффекты

Тело while, как и любой другой блок, может делать I/O — но только если у него есть доступ к capability World (или его кусочку). Функция, в сигнатуре которой нет World, может крутить циклы сколько угодно, но не сможет ничего записать наружу. Это свойство верно и внутри тела цикла; цикл не предоставляет никаких новых capability.

Звучит очевидно, но именно поэтому можно положить while внутрь «чистой» вычислительной функции и всё равно по одной только сигнатуре знать, что она ничего не печатает и не пишет на диск.

Стиль

Несколько маленьких привычек, которые окупаются:

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

Дальше: Shapes

Теперь вы видели весь основной поток управления Zero. Следующая глава — про моделирование данных, начиная с shapes, struct-подобных product-типов Zero.

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

Как работают циклы while в Zero?

Используйте while condition { ... }. Условие вычисляется перед каждой итерацией; если оно true, выполняется тело, и цикл проверяет снова. Если false, цикл выходит, и выполнение продолжается за закрывающей скобкой. Условие должно быть bool.

Есть ли в Zero цикл for?

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

Как написать counted-цикл в Zero?

Инициализируйте счётчик, запустите while против него и обновляйте внутри тела: let mut i = 0; while i < 10 { ...; i = i + 1 }. Синтаксис изменяемости в pre-1.0 Zero ещё эволюционирует, поэтому сверьтесь с актуальной документацией о точном написании — но паттерн «while + счётчик + обновление» это стандартная идиома счётного цикла.

Есть ли в Zero break или continue?

Большинство языков из семейства Zero поставляют какую-то конструкцию раннего выхода для циклов; точное написание в pre-1.0 Zero — одна из областей, которые могут пошевелиться до 1.0. Консервативный подход — устроить цикл так, чтобы само условие делало работу: инвертировать и обновить условие так, чтобы цикл вышел естественно, а не полагаться на конкретное ключевое слово потока управления.

Может ли цикл while в Zero работать вечно?

Да — while true { ... } это бесконечный цикл. Полезно для серверов, event-loop, REPL — всего, где нет естественного условия завершения. В отличие от неявной truthiness, true здесь — это литерал типа bool, поэтому условие хорошо типизировано.

Coddy programming languages illustration

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

НАЧАТЬ