Bug 24649 – Upper-bound-inclusive range foreach

Status
NEW
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2024-07-05T11:16:43Z
Last change time
2024-12-13T19:36:16Z
Assigned to
No Owner
Creator
Bolpat
Moved to GitHub: dmd#18254 →

Comments

Comment #0 by qs.il.paperinik — 2024-07-05T11:16:43Z
A `foreach` loop never includes the upper bound. That is fine most of the time, but when it’s not trivial to generate the sentinel value which is the first not included, writing a such a loop is needlessly hard in D. Examples include cases where the (inclusive) upper bound may realistically be the maximum of its type, which in particular happens for `enum` types. A simple fix would be to recognize the pattern `+ 1` for the upper bound of `foreach`: ```diff UprExpression: Expression + AddExpression + 1 ``` A `L .. U + 1` loop is defined to be an upper-bound-inclusive iteration and works without evaluating or even type-checking `AddExpression + 1`, it only type-checks and evaluates the `AddExpression`. E.g. `ulong.max + 1` does not overflow and `MyEnum.max + 1` does not fail the type checker. The same for `foreach_reverse`. (Maybe, but I’m not sure about this extension, this could be generalized to recognizing any `AddExpression + MulExpression`, trying to CTFE the `MulExpression` and if it evaluates to 0 or 1, generate an upper-bound-exclusive or -inclusive loop, and only in other cases, type-check and evaluate the whole `AddExpression + MulExpression`.)
Comment #1 by dkorpel — 2024-07-05T11:28:53Z
Adding magic rules to the + operator in a specific context is a bad idea. More feasable would be to extend the Range element as a whole, for example like in odin: ``` for i in 0..=9 {} for i in 0..<10 {} ``` https://odin-lang.org/docs/overview/#range-based-for-loop
Comment #2 by qs.il.paperinik — 2024-07-08T16:54:17Z
(In reply to Dennis from comment #1) > More feasable would be to extend the Range element as a whole, for example > like in odin: > > ``` > for i in 0..=9 {} > for i in 0..<10 {} > ``` > > https://odin-lang.org/docs/overview/#range-based-for-loop I get where this is coming from, but in D, already, `..` is with exclusive upper bounds. What I’ve seen, `..` or `...` means inclusive upper bound and `..<` is used for exclusive. We can’t do that. I really thought about that, and just nothing came to my mind that really makes sense. We could use `foreach (i; L ... U)` for inclusive upper bounds, but a single `.` making the difference maybe isn’t a great idea, and, more importantly, `..` looks like the inclusive and `...` the exclusive one, when it’s exactly reverse. (I’d bet there’s a language that does exactly this, but I don’t remember which.) What I’d take from Odin is `..<=`, but not `..=`. A downside I can see people being confused because there being `..<=` implies there is `..<` but that one wouldn’t exist. (There would have to be added a special error message telling people to use just `..` instead of `..<`.) > Adding magic rules to the + operator in a specific context is a bad idea. I don’t see why exactly this is the case. Technically speaking, it wouldn’t even be the `+` operator, it’s part of the `foreach` syntax, similar how in an argument list, or array literals, commas aren’t comma operators, but part of the list syntax.
Comment #3 by robert.schadek — 2024-12-13T19:36:16Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18254 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB