<p>While the C-style <code>for</code> loop syntax is badly designed from a <code>don't repeat yourself</code> perspective, it does offer an advantage over many other languages' loop designs: it makes it easy to specify that a loop should exit when the index <em>reaches</em> a certain value, as opposed to indicating that it should execute once more after that happens.  Code written in other languages is often rife with constructs like:</p>
<pre><code>For I:=0 to Limit-1 Do
</code></pre>
<p>which ends up being more work for the programmer and compiler alike than would a loop which syntactically indicated that the loop should exit as soon as <code>I</code> reaches <code>Limit</code>.</p>
<p>Do any languages other than C provide nice means of indicating whether or not the &quot;index equals boundary&quot; case should mark the end of a loop?  What about indicating that the ending value should be included but the start value shouldn't (common in &quot;count down to zero&quot; loops)?</p>
<p>To clarify the question, I'm interested in languages whose iteration control statements would allow specification of the loop start value, increment amount, direction, the stop value, and whether or not the iteration reachining the stop value should be executed.</p>

<syntax><for-loops>
Loop syntax for inclusive and exclusive end boundaries
<p>C's <code>for</code> loop has three parts: an initialiser for an iteration variable, a condition to check if there are any more values to iterate over, and a &quot;step&quot; which advances the iteration variable to its next value.</p>
<p>More modern languages tend to encapsulate those three things into a single &quot;iterator&quot; object, so that loops can be written more simply by just providing an iterator (or iterable) object for the variable to take its values from. As well as simplifying the syntax of loops, this can also mean that iterator objects can be used in other ways, e.g. as arguments to higher-order functions like <code>map</code> and <code>filter</code> ─ and iterable range objects have other uses like membership tests.</p>
<p>So the approach of languages like this is to provide iterable objects which represent ranges of numbers. The most common types of range are</p>
<ul>
<li>Half-open, including <code>a</code> but not <code>b</code>, e.g. <code>range(a, b)</code> in Python, <code>a..b</code> in Rust.</li>
<li>Closed, including both <code>a</code> and <code>b</code>, e.g. <code>range(a, b+1)</code> in Python, <code>a..=b</code> in Rust.</li>
<li>Open, including neither <code>a</code> nor <code>b</code>, e.g. <code>range(a+1, b)</code> in Python, <code>(a+1)..b</code> in Rust.</li>
<li>The other kind of half-open, including <code>b</code> but not <code>a</code>, e.g. <code>range(a+1, b+1)</code> in Python, <code>(a+1)..=b</code> in Rust.</li>
</ul>
<p>Notably, the syntax in both cases is not so neat for the less common types of range, but this is probably more to do with their relative rarity rather than the difficulty of providing syntax:</p>
<ul>
<li>Python could just as well have separate constructors for <code>range</code>, <code>closed_range</code>, <code>open_range</code> and so on, or they could be static methods like <code>range.closed</code>, or the kind of range could be controlled by optional keyword arguments like <code>range(a, b, closed_start=False, closed_end=True)</code>.</li>
<li>Rust could support <code>a&lt;..b</code> and <code>a&lt;..=b</code> as syntaxes for other types of range. This would be implemented by just having <code>&lt;..</code> and <code>&lt;..=</code> as individual tokens to represent range constructor operations, just as <code>..</code> and <code>..=</code> already are.</li>
</ul>
<p>This also gets more complicated when you want ranges with different step sizes, including reversed ranges. Python's syntax is better for this than a Rust-style syntax would be: the <code>range</code> constructor takes an optional third argument like <code>range(a, b, step)</code>. Another benefit of having range constructors be named functions is that they are easier to search for, whereas punctuation like <code>&lt;..=</code> can't be put into most search engines when seen by a user unfamiliar with them.</p>

CC BY-SA 4.0
2023-07-02T17:50:42.707Z
2023-07-02T18:53:02.070Z
2023-07-02T18:53:02.070Z
kaya3
CC BY-SA 4.0
2023-07-02T17:58:36.857Z
All of those feel needlessly clunky.  It would seem cleaner to extending C-like syntax to say that if the the first term of a `for` loop declares/defines exactly one object, the second term may start with a comparison operator and the third term may start with an indrement, decrement, or compound assignment operator; in such cases, the second or third term would behave as though it started with the item that was declared.  An alternative would be to say that a `for` loop may include a single term if it's only used with compound statements...
supercat
CC BY-SA 4.0
2023-07-02T17:59:43.057Z
...and such statements may be separated by predicates containing expressions.  Requiring compound statements would allow predictates to be marked with non-reserved words, since no other identifiers could appear in such contexts.
supercat
CC BY-SA 4.0
2023-07-02T18:01:09.357Z
@supercat If you have an idea for an alternative which extends the C-like syntax, please write it in an answer. I do not follow what you mean about predicates and compound statements, but you would be able to explain that in an answer if you wrote one.
kaya3
CC BY-SA 4.0
2023-07-02T18:13:27.650Z
My question was whether any nice syntactic forms exist.  I would think that in the last 50 years, someone smarter than me should have come up with something nicer than anything I could come up with, even if it never managed to gain much traction (perhaps it was a great feature in a language that wasn't well suited for popular tasks).
supercat
CC BY-SA 4.0
2023-07-02T18:35:41.127Z
Your question asks *"Do any languages other than C provide nice means of indicating whether or not the "index equals boundary" case should mark the end of a loop?"*, and that's the distinction between `a..b` and `a..=b` ranges in Rust. Whether or not it's nice is a matter of opinion, but the Rust designers evidently thought it was nice enough to include in the language. In any case, the content of your comments looks like a proposal for a different syntax which belongs in an answer, not a request for clarification or suggesting an improvement for this answer.
kaya3
CC BY-SA 4.0
2023-07-02T18:42:15.693Z
I guess the intention of the question was "Do any languages do something nicer than what could be accomplished by hacking C syntax.  My beef with Python is the need for silly (and potentially breaking) arithmetic in the "inclusive" case.  Conceptually, Rust seems good for increment-by-one ranges, but I don't see any mention of ways of handling other increments or downward counting.  If I recall, Pascall allowed `For I:=0 to 10 by 5 do`, and also allowed downward count using `downto` instead of `to`, but lacked any way to specify a non-inclusive limit.
supercat
CC BY-SA 4.0
2023-07-02T18:45:08.723Z
@supercat The last paragraph of my answer mentions other step sizes, including negative step sizes. If your opinion is that how Python and Rust handle this is insufficiently nice for your tastes, then your opinion is duly noted. If Pascal has a different syntax then that again is an answer, I do not think there is any edit I should make to address it.
kaya3
CC BY-SA 4.0
2023-07-02T18:50:00.883Z
I interpreted the lack of any indication as to how Rust handles those cases as implying that one would have to do something horrible.  Python by the sound of it simply uses an exclusive range end all of the time rather than using inclusive range end all of the time like BASIC and Pascal do, but doesn't offer programmers a choice.  If Rust has a non-horrible syntax for those other cases, your answer could be improved by describing them.
supercat
CC BY-SA 4.0
2023-07-02T18:55:00.110Z
Rust doesn't have a syntax for ranges with different step sizes, I have edited to clarify that I meant Python's syntax for this is better than if Rust's syntax were extended to cover this use-case.
kaya3
CC BY-SA 4.0
2023-07-02T19:07:28.883Z
Using the Rust approach, I would think it would be cleanest to specify the range in the usual half-open-range style but then indicate that it should be iterated in reverse, and/or that one should process every Nth item.  Otherwise, I find myself thinking that something like Pascal but with `until` rather than `to` or `downto` might be nice.
supercat
CC BY-SA 4.0
2023-07-02T19:15:57.420Z
@supercat Again, your opinion is noted but I do not know what action you want me to take in response to it. Please remember that comments are supposed to be used to request clarification or propose improvements; if you have ideas about how to answer the question differently then you should write them in an answer.
kaya3
CC BY-SA 4.0
2023-07-03T15:46:48.527Z
I've added some clarification to the question, but I remain curious: if one wanted a loop that counted from 255 to 0, or counted from 0 to 255 advancing by 3, would there be a nice way of specifying that in Rust?
supercat
CC BY-SA 4.0
2023-07-03T15:48:57.153Z
As I wrote above, Rust doesn't have a syntax for ranges with different step sizes.
kaya3
CC BY-SA 4.0
2023-07-03T15:54:33.200Z
If one wants to write a program that outputs the numbers 255, 254, 253, etc. down to 0, or otuputs values 0, 3, 6, etc. up to 255, there must be *some* way of performing such a task in Rust.  I can't imagine the language could have become very popular for low-level programming without a way of accomplishing such a thing reasonably efficiently.  Would the normal paradigm just be to use some sort of "while" loop?
supercat
CC BY-SA 4.0
2023-07-03T16:14:18.280Z
@supercat Of course you can write a `while` loop; you can do so in almost any imperative language. But there are other ways of solving problems which don't require manual indexing into arrays or buffers, so if a loop like `for(let i = 0; i < arr.length; i += 4)` is a good solution to a problem in C or Java it does not imply that an equivalent loop is a good solution to the same problem in Rust. I appreciate that you are curious, but if you have questions about how to write idiomatically in Rust then a Rust discussion forum is the appropriate place to ask.
kaya3
<p>Included for completeness you could use the mathematical notation of different bracket types for open and closed ranges.
E.g.</p>
<pre><code>[a,b]
[a,b)
(a,b)
(a,b]
</code></pre>
<p>See <a href="https://en.wikipedia.org/wiki/Interval_(mathematics)" rel="nofollow noreferrer">https://en.wikipedia.org/wiki/Interval_(mathematics)</a></p>
<p>This is anathema to most programmers as we like our brackets to balance.</p>

CC BY-SA 4.0
2023-07-03T12:43:20.160Z
2023-07-03T12:43:20.160Z
Bruce Adams
<p>I had thought about it, and my idea was</p>
<pre><code>for (lhs relop1 variable relop2 rhs) {
}
</code></pre>
<p>relop1 and relop2 are either both &lt;= or &lt;, or both &gt;= or &gt;. lhs and rhs are evaluate once. variable iterates over all integer values of the right type where both relops are true, in ascending order for &lt; / &lt;= and descending order for &gt; / &gt;=.</p>
<p>For example</p>
<pre><code>char* s; size_t i;
for (strlen (s) &gt; i &gt;= 0) {
}
</code></pre>
<p>would cleanly operate on all string elements in reverse order, stopping properly at i = 0.</p>

CC BY-SA 4.0
2023-07-03T14:25:34.363Z
2023-07-03T14:25:34.363Z
gnasher729
# Loop syntax for inclusive and exclusive end boundaries
Posted by: username_0 on 2023-07-02
While the C-style for loop syntax is badly designed from a don't repeat yourself perspective, it does offer an advantage over many other languages' loop designs: it makes it easy to specify that a loop should exit when the index reaches a certain value, as opposed to indicating that it should execute once more after that happens.  Code written in other languages is often rife with constructs like:
For I:=0 to Limit-1 Do

which ends up being more work for the programmer and compiler alike than would a loop which syntactically indicated that the loop should exit as soon as I reaches Limit.
Do any languages other than C provide nice means of indicating whether or not the "index equals boundary" case should mark the end of a loop?  What about indicating that the ending value should be included but the start value shouldn't (common in "count down to zero" loops)?
To clarify the question, I'm interested in languages whose iteration control statements would allow specification of the loop start value, increment amount, direction, the stop value, and whether or not the iteration reachining the stop value should be executed.
**Tags:** syntax for-loops
---
## 3 answers
### Answer by username_1 on 2023-07-02. Score: 4
C's `for` loop has three parts: an initialiser for an iteration variable, a condition to check if there are any more values to iterate over, and a "step" which advances the iteration variable to its next value.

More modern languages tend to encapsulate those three things into a single "iterator" object, so that loops can be written more simply by just providing an iterator (or iterable) object for the variable to take its values from. As well as simplifying the syntax of loops, this can also mean that iterator objects can be used in other ways, e.g. as arguments to higher-order functions like `map` and `filter` ─ and iterable range objects have other uses like membership tests.

So the approach of languages like this is to provide iterable objects which represent ranges of numbers. The most common types of range are

* Half-open, including `a` but not `b`, e.g. `range(a, b)` in Python, `a..b` in Rust.
* Closed, including both `a` and `b`, e.g. `range(a, b+1)` in Python, `a..=b` in Rust.
* Open, including neither `a` nor `b`, e.g. `range(a+1, b)` in Python, `(a+1)..b` in Rust.
* The other kind of half-open, including `b` but not `a`, e.g. `range(a+1, b+1)` in Python, `(a+1)..=b` in Rust.

Notably, the syntax in both cases is not so neat for the less common types of range, but this is probably more to do with their relative rarity rather than the difficulty of providing syntax:

* Python could just as well have separate constructors for `range`, `closed_range`, `open_range` and so on, or they could be static methods like `range.closed`, or the kind of range could be controlled by optional keyword arguments like `range(a, b, closed_start=False, closed_end=True)`.
* Rust could support `a<..b` and `a<..=b` as syntaxes for other types of range. This would be implemented by just having `<..` and `<..=` as individual tokens to represent range constructor operations, just as `..` and `..=` already are.

This also gets more complicated when you want ranges with different step sizes, including reversed ranges. Python's syntax is better for this than a Rust-style syntax would be: the `range` constructor takes an optional third argument like `range(a, b, step)`. Another benefit of having range constructors be named functions is that they are easier to search for, whereas punctuation like `<..=` can't be put into most search engines when seen by a user unfamiliar with them.
> **Comments:**
> **username_0** (2023-07-02): All of those feel needlessly clunky.  It would seem cleaner to extending C-like syntax to say that if the the first term of a `for` loop declares/defines exactly one object, the second term may start with a comparison operator and the third term may start with an indrement, decrement, or compound assignment operator; in such cases, the second or third term would behave as though it started with the item that was declared.  An alternative would be to say that a `for` loop may include a single term if it's only used with compound statements...  
> **username_0** (2023-07-02): ...and such statements may be separated by predicates containing expressions.  Requiring compound statements would allow predictates to be marked with non-reserved words, since no other identifiers could appear in such contexts.  
> **username_1** (2023-07-02): @supercat If you have an idea for an alternative which extends the C-like syntax, please write it in an answer. I do not follow what you mean about predicates and compound statements, but you would be able to explain that in an answer if you wrote one.  
> **username_0** (2023-07-02): My question was whether any nice syntactic forms exist.  I would think that in the last 50 years, someone smarter than me should have come up with something nicer than anything I could come up with, even if it never managed to gain much traction (perhaps it was a great feature in a language that wasn't well suited for popular tasks).  
> **username_1** (2023-07-02): Your question asks *"Do any languages other than C provide nice means of indicating whether or not the "index equals boundary" case should mark the end of a loop?"*, and that's the distinction between `a..b` and `a..=b` ranges in Rust. Whether or not it's nice is a matter of opinion, but the Rust designers evidently thought it was nice enough to include in the language. In any case, the content of your comments looks like a proposal for a different syntax which belongs in an answer, not a request for clarification or suggesting an improvement for this answer.  
> **username_0** (2023-07-02): I guess the intention of the question was "Do any languages do something nicer than what could be accomplished by hacking C syntax.  My beef with Python is the need for silly (and potentially breaking) arithmetic in the "inclusive" case.  Conceptually, Rust seems good for increment-by-one ranges, but I don't see any mention of ways of handling other increments or downward counting.  If I recall, Pascall allowed `For I:=0 to 10 by 5 do`, and also allowed downward count using `downto` instead of `to`, but lacked any way to specify a non-inclusive limit.  
> **username_1** (2023-07-02): @supercat The last paragraph of my answer mentions other step sizes, including negative step sizes. If your opinion is that how Python and Rust handle this is insufficiently nice for your tastes, then your opinion is duly noted. If Pascal has a different syntax then that again is an answer, I do not think there is any edit I should make to address it.  
> **username_0** (2023-07-02): I interpreted the lack of any indication as to how Rust handles those cases as implying that one would have to do something horrible.  Python by the sound of it simply uses an exclusive range end all of the time rather than using inclusive range end all of the time like BASIC and Pascal do, but doesn't offer programmers a choice.  If Rust has a non-horrible syntax for those other cases, your answer could be improved by describing them.  
> **username_1** (2023-07-02): Rust doesn't have a syntax for ranges with different step sizes, I have edited to clarify that I meant Python's syntax for this is better than if Rust's syntax were extended to cover this use-case.  
> **username_0** (2023-07-02): Using the Rust approach, I would think it would be cleanest to specify the range in the usual half-open-range style but then indicate that it should be iterated in reverse, and/or that one should process every Nth item.  Otherwise, I find myself thinking that something like Pascal but with `until` rather than `to` or `downto` might be nice.  
> **username_1** (2023-07-02): @supercat Again, your opinion is noted but I do not know what action you want me to take in response to it. Please remember that comments are supposed to be used to request clarification or propose improvements; if you have ideas about how to answer the question differently then you should write them in an answer.  
> **username_0** (2023-07-03): I've added some clarification to the question, but I remain curious: if one wanted a loop that counted from 255 to 0, or counted from 0 to 255 advancing by 3, would there be a nice way of specifying that in Rust?  
> **username_1** (2023-07-03): As I wrote above, Rust doesn't have a syntax for ranges with different step sizes.  
> **username_0** (2023-07-03): If one wants to write a program that outputs the numbers 255, 254, 253, etc. down to 0, or otuputs values 0, 3, 6, etc. up to 255, there must be *some* way of performing such a task in Rust.  I can't imagine the language could have become very popular for low-level programming without a way of accomplishing such a thing reasonably efficiently.  Would the normal paradigm just be to use some sort of "while" loop?  
> **username_1** (2023-07-03): @supercat Of course you can write a `while` loop; you can do so in almost any imperative language. But there are other ways of solving problems which don't require manual indexing into arrays or buffers, so if a loop like `for(let i = 0; i < arr.length; i += 4)` is a good solution to a problem in C or Java it does not imply that an equivalent loop is a good solution to the same problem in Rust. I appreciate that you are curious, but if you have questions about how to write idiomatically in Rust then a Rust discussion forum is the appropriate place to ask.  
---
### Answer by username_2 on 2023-07-03. Score: 2
Included for completeness you could use the mathematical notation of different bracket types for open and closed ranges.
E.g.
[a,b]
[a,b)
(a,b)
(a,b]

See https://en.wikipedia.org/wiki/Interval_(mathematics)
This is anathema to most programmers as we like our brackets to balance.
---
### Answer by username_3 on 2023-07-03. Score: 1
I had thought about it, and my idea was
for (lhs relop1 variable relop2 rhs) {
}

relop1 and relop2 are either both <= or <, or both >= or >. lhs and rhs are evaluate once. variable iterates over all integer values of the right type where both relops are true, in ascending order for < / <= and descending order for > / >=.
For example
char* s; size_t i;
for (strlen (s) > i >= 0) {
}

would cleanly operate on all string elements in reverse order, stopping properly at i = 0.
---
