Thread overview
Do Loop with Variable
Jul 08
jmh530
Jul 17
Dukc
July 08

I have the feeling this isn’t gonna fly, but I’ll say it anyways because maybe someone finds a solution.

do (int x = 0)
{ }
while (++x < 10);

which would be equivalent to

{
    int x = 0;
    do
    { }
    while (++x < 10);
}

Obviously, we can’t just parse do plus the opening parenthesis because things like do (x + y).ufcs while (…) certainly exist. But it can be parsed:

After do plus opening parenthesis, scan for the closing parenthesis. From there, if an opening brace follows, scan for the closing brace. If the closing brace is followed by while, it’s the new construct.

The new construct must use braces, otherwise ambiguity lurks.

July 08

On Tuesday, 8 July 2025 at 16:40:24 UTC, Quirin Schroll wrote:

>

I have the feeling this isn’t gonna fly, but I’ll say it anyways because maybe someone finds a solution.

do (int x = 0)
{ }
while (++x < 10);

which would be equivalent to

{
    int x = 0;
    do
    { }
    while (++x < 10);
}

[snip]

What is your motivation for this? Making sure x doesn't stay around or making sure it doesn't conflict with x elsewhere in the program?

July 09

On Tuesday, 8 July 2025 at 17:24:11 UTC, jmh530 wrote:

>

On Tuesday, 8 July 2025 at 16:40:24 UTC, Quirin Schroll wrote:

>

I have the feeling this isn’t gonna fly, but I’ll say it anyways because maybe someone finds a solution.

do (int x = 0)
{ }
while (++x < 10);

which would be equivalent to

{
    int x = 0;
    do
    { }
    while (++x < 10);
}

[snip]

What is your motivation for this? Making sure x doesn't stay around or making sure it doesn't conflict with x elsewhere in the program?

Exactly that. I really would like to have this also in C.
I would even go as far as having a special scope rule only applying to do {} while(). Where the scope extends to closing parenthesis of the while.

    do {
       int a = 0;
       ...
    } while(a++ < 10);

I know that something like that would never fly.

July 17

On Wednesday, 9 July 2025 at 17:13:27 UTC, Patrick Schluter wrote:

>

On Tuesday, 8 July 2025 at 17:24:11 UTC, jmh530 wrote:

>

On Tuesday, 8 July 2025 at 16:40:24 UTC, Quirin Schroll wrote:

>

I have the feeling this isn’t gonna fly, but I’ll say it anyways because maybe someone finds a solution.

do (int x = 0)
{ }
while (++x < 10);

which would be equivalent to

{
    int x = 0;
    do
    { }
    while (++x < 10);
}

[snip]

What is your motivation for this? Making sure x doesn't stay around or making sure it doesn't conflict with x elsewhere in the program?

Exactly that. I really would like to have this also in C.
I would even go as far as having a special scope rule only applying to do {} while(). Where the scope extends to closing parenthesis of the while.

    do {
       int a = 0;
       ...
    } while(a++ < 10);

I know that something like that would never fly.

In C, yeah, it’s not gonna be added. But D? It could be added. D doesn’t allow local variable shadowing, which means that a in while (a++ < 10) can’t be another local variable (because that would shadow the one defined in the loop body). It could theoretically be a member or global variable, though, but I doubt anyone would intentionally write such code (likely it’s a bug).

Essentially, it would mean that

do Statement while (Condition);

would be equivalent to:

{
start:
    Statement
    if (Condition) goto start;
}

instead of:

{
start:
    { Statement }
    if (Condition) goto start;
}

It wouldn’t be the only {} that don’t introduce scope. static if/version/debug don’t introduce scope and the first for doesn’t introduce scope either:

for ({int i; double d = 10;} i < 10; ++i, d /= 2) { }
July 17

On Tuesday, 8 July 2025 at 16:40:24 UTC, Quirin Schroll wrote:

>

I have the feeling this isn’t gonna fly, but I’ll say it anyways because maybe someone finds a solution.

do (int x = 0)
{ }
while (++x < 10);

which would be equivalent to

{
    int x = 0;
    do
    { }
    while (++x < 10);
}

I would probably prefer if symbols declared inside the do statement would be accessible in the condition. Would be a breaking change though, requiring a warning from the compiler if a symbol declared both inside and outside the do block would be used in while and probably doing it over an edition switch.

July 28

On Thursday, 17 July 2025 at 13:43:33 UTC, Dukc wrote:

>

On Tuesday, 8 July 2025 at 16:40:24 UTC, Quirin Schroll wrote:

>

I have the feeling this isn’t gonna fly, but I’ll say it anyways because maybe someone finds a solution.

do (int x = 0)
{ }
while (++x < 10);

which would be equivalent to

{
    int x = 0;
    do
    { }
    while (++x < 10);
}

I would probably prefer if symbols declared inside the do statement would be accessible in the condition. Would be a breaking change though, requiring a warning from the compiler if a symbol declared both inside and outside the do block would be used in while and probably doing it over an edition switch.

Realistically, if you reference a symbol that’s defined within the loop in the condition that coincidentally resolves because it’s also defined in the outer scope, that should be an error. You can always refer to such a symbol in an unambiguous way. Here’s what I mean:

struct S
{
    int x;
    void f()
    {
        do { int x; …; }
        while (x > 0); // likely a bug
    }
}

The x in x > 0 refers to this.x, not the local variable defined in the loop. My sense is: No-one actually writes such code intentionally. If it really makes sense to name a do-loop-body variable the same as an outer-scope variable used in its condition, it’s not too much to ask to make this clear: Use this.x or .x (global) or whatever. (I filed this as an issue.)

July 31

On Tuesday, 8 July 2025 at 16:40:24 UTC, Quirin Schroll wrote:

>

I have the feeling this isn’t gonna fly, but I’ll say it anyways because maybe someone finds a solution.

do (int x = 0)
{ }
while (++x < 10);

which would be equivalent to

{
    int x = 0;
    do
    { }
    while (++x < 10);
}

Obviously, we can’t just parse do plus the opening parenthesis because things like do (x + y).ufcs while (…) certainly exist. But it can be parsed:

After do plus opening parenthesis, scan for the closing parenthesis. From there, if an opening brace follows, scan for the closing brace. If the closing brace is followed by while, it’s the new construct.

The new construct must use braces, otherwise ambiguity lurks.

I think this is of limited utility and there's a workaround.

August 01

On Thursday, 31 July 2025 at 08:38:18 UTC, Atila Neves wrote:

>

On Tuesday, 8 July 2025 at 16:40:24 UTC, Quirin Schroll wrote:

>

I have the feeling this isn’t gonna fly, but I’ll say it anyways because maybe someone finds a solution.

do (int x = 0)
{ }
while (++x < 10);

which would be equivalent to

{
    int x = 0;
    do
    { }
    while (++x < 10);
}

Obviously, we can’t just parse do plus the opening parenthesis because things like do (x + y).ufcs while (…) certainly exist. But it can be parsed:

After do plus opening parenthesis, scan for the closing parenthesis. From there, if an opening brace follows, scan for the closing brace. If the closing brace is followed by while, it’s the new construct.

The new construct must use braces, otherwise ambiguity lurks.

I think this is of limited utility and there's a workaround.

What’s your opinion on the issue that eponymous symbols can be referenced, leading to bugs? See this thread entry. D often bans things that have well-defined semantics in similar languages, but are confusing and easily lead to bugs, especially if being more explicit simply avoids the confusion. Examples include:

  • Plain assignment expressions cannot be used as conditions.
  • Combining => {} isn’t allowed.
  • Bitwise and comparison operators require parentheses.
  • Shadowing a local variable isn’t allowed.

It’d be very much in the same spirit as the last bullet point, just in reverse.