From d475aedadb8d719ef5a87bd3792f1498ed18eba3 Mon Sep 17 00:00:00 2001 From: Michal Makowski Date: Tue, 8 Jul 2025 11:59:12 +0200 Subject: [PATCH] Proposal: do-while loops abstract --- proposals/p5671.md | 204 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 proposals/p5671.md diff --git a/proposals/p5671.md b/proposals/p5671.md new file mode 100644 index 0000000000000..095f16a5daf9e --- /dev/null +++ b/proposals/p5671.md @@ -0,0 +1,204 @@ +# Do...while loops + + + +[Pull request](https://github.com/carbon-language/carbon-lang/pull/####) + + + +## Table of contents + +- [Abstract](#abstract) +- [Problem](#problem) +- [Background](#background) +- [Proposal](#proposal) +- [Details](#details) + - [Syntax](#syntax) + - [Semantics](#semantics) + - [Examples](#examples) + - [Interaction with break and continue](#interaction-with-break-and-continue) +- [Rationale](#rationale) +- [Alternatives considered](#alternatives-considered) + - [Alternative syntax forms](#alternative-syntax-forms) + - [Not adding do...while loops](#not-adding-dowhile-loops) + - [Using repeat...until instead](#using-repeatuntil-instead) + + + +## Abstract + +This proposal adds `do...while` loops to Carbon, providing a post-test loop construct that executes the loop body at least once before checking the condition. This complements the existing `while` and `for` loop constructs. + +## Problem + +Carbon currently provides `while` and `for` loops, but lacks a post-test loop construct. There are common programming patterns where you need to execute a block of code at least once and then repeat it based on a condition. Currently, these patterns require either: + +1. Code duplication (writing the loop body before the `while` loop) +2. Using a `while (true)` loop with a `break` statement +3. Using a boolean flag to ensure the first iteration + +These workarounds make code less readable and more error-prone. A `do...while` construct would provide a clean, idiomatic solution for these use cases. + +## Background + +Many programming languages provide post-test loop constructs: + +- C, C++, Java, C#, and JavaScript use `do...while` +- Some languages like Pascal use `repeat...until` (with inverted condition logic) +- Python notably lacks this construct, leading to similar workarounds + +Common use cases for post-test loops include: + +- Input validation loops (prompt user until valid input is provided) +- Menu systems (show menu at least once, repeat based on user choice) +- Game loops (execute game logic at least once per frame) +- Retry mechanisms (attempt operation at least once, retry on failure) +- Processing loops where you need to read/process at least one item + +## Proposal + +Add `do...while` loops to Carbon with the following syntax: + +```carbon +do { + // statements +} while (condition); +``` + +The loop body executes at least once, and then the condition is evaluated. If the condition is `True`, the loop continues; if `False`, the loop terminates. + +## Details + +### Syntax + +The syntax for `do...while` loops is: + +> `do {` _statements_ `} while (` _boolean expression_ `);` + +Key syntax elements: +- The `do` keyword introduces the loop +- The loop body is enclosed in braces `{}` +- The `while` keyword and condition follow the closing brace +- A semicolon `;` terminates the statement + +### Semantics + +1. The loop body executes unconditionally on the first iteration +2. After each iteration, the boolean expression is evaluated +3. If the expression evaluates to `True`, execution returns to the beginning of the loop body +4. If the expression evaluates to `False`, execution continues after the loop +5. The boolean expression must have type `Bool` or be implicitly convertible to `Bool` + +### Examples + +**Input validation:** +```carbon +var input: String; +do { + Print("Enter a positive number: "); + input = ReadLine(); +} while (!IsValidPositiveNumber(input)); +``` + +**Menu system:** +```carbon +var choice: Int; +do { + PrintMenu(); + choice = ReadChoice(); + ProcessChoice(choice); +} while (choice != 0); +``` + +**Processing with at-least-once guarantee:** +```carbon +var data: Array(String) = LoadInitialData(); +do { + ProcessBatch(data); + data = LoadNextBatch(); +} while (!data.IsEmpty()); +``` + +**Retry mechanism:** +```carbon +var success: Bool; +var attempts: Int = 0; +do { + success = TryOperation(); + ++attempts; +} while (!success && attempts < MaxRetries); +``` + +### Interaction with break and continue + +`do...while` loops support the same control flow statements as other loops: + +- `break` immediately exits the loop, skipping the condition check +- `continue` skips to the condition check, potentially starting the next iteration + +**Example with break:** +```carbon +do { + var input: String = ReadLine(); + if (input == "quit") { + break; + } + ProcessInput(input); +} while (true); +``` + +**Example with continue:** +```carbon +do { + var value: Int = GetNextValue(); + if (value < 0) { + continue; // Skip negative values + } + ProcessValue(value); +} while (HasMoreValues()); +``` + +## Rationale + +This proposal advances Carbon's goals in several ways: + +- **[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)**: `do...while` loops make post-test loop patterns more explicit and readable than workarounds with `while (true)` and `break` statements. + +- **[Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)**: C++ developers are familiar with `do...while` loops, making Carbon more approachable for migration. + +- **[Performance-critical software](/docs/project/goals.md#performance-critical-software)**: Eliminates the need for boolean flags or code duplication that might impact performance in tight loops. + +The syntax follows Carbon's existing patterns: +- Consistent with `while` loops in using parentheses around the condition +- Consistent with Carbon's requirement for braces around statement blocks +- The semicolon terminator follows C-family language conventions + +## Alternatives considered + +### Not adding do...while loops + +We could choose not to add `do...while` loops and continue using workarounds. However: + +- Code duplication is error-prone and violates DRY principles +- `while (true)` with `break` is less clear about intent +- Boolean flag approaches add unnecessary complexity +- The construct is common enough in other languages to warrant inclusion + +### Using repeat...until instead + +**Alternative syntax:** +```carbon +repeat { + // statements +} until (condition); +``` + +This was considered but rejected because: +- It inverts the condition logic compared to `while` loops, which could be confusing +- `do...while` is more familiar to developers from C-family languages +- It would require introducing two new keywords (`repeat` and `until`) instead of reusing `while` +- The condition inversion makes it harder to convert between `while` and `do...while` loops \ No newline at end of file