fsharp icon indicating copy to clipboard operation
fsharp copied to clipboard

while ... do: inconsistent handling of whitespace / indentation

Open mathias-brandewinder opened this issue 5 months ago • 6 comments

while ... do expressions handle whitespace / indentation in a manner that is not consistent with if ... then ... else expressions.
This is problematic when the test expression is lengthy and would be more clearly written using multiple lines, along the lines of:

while
    x > 10
    &&
    x < 20
do ...   

Repro steps

Provide the steps required to reproduce the problem:

let mutable x = 0
while
    x < 10
do
    x <- x + 1

Expected behavior

I would expect this to be valid syntax, in a fashion similar to

if
    x < 10
then
    // do something
else
    // do something

Actual behavior

error FS0010: Incomplete structured construct at or before this point in expression Missing 'do' in 'while' expression. Expected 'while <expr> do <expr>'.

Known workarounds

Any indentation of do resolves the issue:

let mutable x = 0
while 
    x < 10
 do
    x <- x + 1

mathias-brandewinder avatar Jul 12 '25 20:07 mathias-brandewinder

The current behavior is in line with the F# spec. do is part of the while context and therefore needs to be indented like anything else. (The same is true for do in for contexts.) For then/else/elif there is an explicit exception to the rule (see §15.1.9 of the F# spec) for good reasons (common case, avoiding multiple indentations). But I wouldn't introduce any further complexity into the compiler for this case.

Martin521 avatar Jul 13 '25 07:07 Martin521

This is indeed a language suggestion. However, it is also in line with previous indentation relaxations -

Happypig375 avatar Jul 13 '25 13:07 Happypig375

Definitely agree with @Happypig375 here - there are two 'expression' holes in a while ... do ... construction, and it feels very wrong for the 'holes' not to be able to be indented separately from the control-flow constructs. @mathias-brandewinder asked me about this yesterday, and I was actually stumped - having used this language for more than a decade - about why the behavior would be the way it is.

The main reason I can think of not to do this is syntactic ambiguity between do block in a while ... do ... vs a 'bare' do block - this I think the parser already is capable enough of handling that.

baronfel avatar Jul 13 '25 13:07 baronfel

This might also be applicable to for ... = ... to ... do, for ... = ... downto ... do and for ... in ... do loops too.

Happypig375 avatar Jul 13 '25 14:07 Happypig375

i.e. a new RFC building upon FS-1108 - Undentation Frenzy with this?

Examples

1. while ... do ...

Currently invalid:

let mutable x = 0
while
    x < 10
    && x > -10
do
    x <- x + 1

Would become valid.

2. for ... = ... to ... do ...

Currently invalid:

for i =
    1
    + 2
    to
    10
    + 5
do
    printfn "%d" i

Would become valid.

3. for ... = ... downto ... do ...

Currently invalid:

for i =
    10
    * 2
    downto
    1
    + 1
do
    printfn "%d" i

Would become valid.

4. for ... in ... do ...

Currently invalid:

for item in
    someVeryLongFunctionNameThatReturnsASequence
        param1
        param2
        param3
do
    printfn "%A" item

Would become valid.

T-Gro avatar Jul 22 '25 08:07 T-Gro

@T-Gro Yes.

let mutable x = 0
while
    x < 10
    && x > -10
do // should be able to undent here
    x <- x + 1

for i =
    1
    + 2
to // should be able to undent here
    10
    + 5
do // should be able to undent here
    printfn "%d" i

for i =
    10
    * 2
downto // should be able to undent here
    1
    + 1
do // should be able to undent here
    printfn "%d" i

for
    item
in // should be able to undent here
    someVeryLongFunctionNameThatReturnsASequence
        param1
        param2
        param3
do // should be able to undent here
    printfn "%A" item

In addition to those 4 cases, the 2 suggestions of

  • https://github.com/fsharp/fslang-suggestions/issues/1111
  • https://github.com/fsharp/fslang-suggestions/issues/1433

should also be considered.

Happypig375 avatar Jul 22 '25 09:07 Happypig375