I suggest we ...

Relax some of the indentation rules

Currently, the general rules for indentation in F# is that the code on the next line should be indented further than the thing that determines its starting point on the previous line.

There are a number of cases where this quite annoyingly means that you have to indent things very far (or, to avoid that, add lots of unnecessary line breaks). One example is when you have nesting in a method call. For example:

|> Chart.WithOptions(Options(colorAxis=ColorAxis(values=[| -100;0;100;200;1000 |], colors=[| "#77D53D";"#D1C855";"#E8A958";"#EA4C41";"#930700" |])))

Now, there is almost no way to make this code snippet look decent. I would want to write something like this:

|> Chart.WithOptions(Options(colorAxis=ColorAxis(values=[| -100;0;100;200;1000 |],
colors=[| "#77D53D";"#D1C855";"#E8A958";"#EA4C41";"#930700" |])))

But this is not allowed, because "colors" should start after the opening parenthesis of ColorAxis, so I would need 50 spaces! To make the number of spaces smaller, you can add additional newline (to get the "ColorAxis" more to the left), but this looks pretty bad:

|> Chart.WithOptions
(colorAxis =
(values=[| -100;0;100;200;1000 |],
colors=[| "#77D53D";"#D1C855";"#E8A958";"#EA4C41";"#930700" |])))

Another example is very similar, but with list expressions. I want to write:

let pop2010 = series [ for c in wb.Countries ->
c.Name => c.Indicators.``CO2 emissions (kt)``.[2010]]

This actually works, but it gives warning. Again, it wants me to indent the second line so that it is after "for", but then I'm not saving pretty much anything by the newline. Or, I can introduce lots of additional newlines and write:

let pop2010 =
[ for c in wb.Countries ->
c.Name => c.Indicators.``CO2 emissions (kt)``.[2010]]

I think that in situations like these, the rules should be relaxed. In particular, we should not require new line to be intended further than the "starting thing" on the previous line. Just further than the previous line.

55 votes
Sign in
Sign in with: facebook google
Signed in as (Sign out)
You have left! (?) (thinking…)
Tomas Petricek shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →


Sign in
Sign in with: facebook google
Signed in as (Sign out)
  • Robin Munn commented  ·   ·  Flag as inappropriate

    BTW, records have been mentioned in a separate suggestion: https://fslang.uservoice.com/forums/245727-f-language/suggestions/15696774-relax-indentation-rules-on-records

    I feel the records idea is a subset of this one, which would also cover lists and arrays (and so on). So although I'm 100% in favor of the records suggestion, I've put my limited votes on this one instead.

    Also, I'd like to mention one thing that I haven't seen mentioned yet. I'd like to be able to put the closing delimiter on a line of its own, indented at the same level as the following code. E.g.,

    let myFunction () =
    ....let someList = [
    ....let otherList = [1; 2; 3]
    ....// Other code follows

  • Alexandre Szymocha commented  ·   ·  Flag as inappropriate

    I LOVE this proposition!

    I’m currently using
    #nowarn "62"
    #light "off"
    at the top of every file. This removes the pythonic indentation and allows me to write my code shapelessly, but it’s tedious.

  • Fredrik Forssen commented  ·   ·  Flag as inappropriate

    What annoys me most is the records. I would prefer to be able to use something looking like the K&R bracing for records, but the F# compiler wants me to either write oneliners or indenting a lot (or putting the braces on their own lines, heresy!)

    I'd love to be able to do this (. instead of space since uservoice hates whitespace)

    type Person = {
    ....Name : string
    ....Age : int

    let calvin = {
    ....Name = "Calvin
    ....Age = 8

  • DK commented  ·   ·  Flag as inappropriate

    As a matter of fact, I don't find the solution to the problem that you've posted to be that bad. I do however prefer it in a slightly different style: http://fssnip.net/s0

    Given enough complexity even this would start becoming too unwieldy, and would require extracting values out into let bindings. But for this example, I personally think this is more than sufficient.

F# Language

Feedback and Knowledge Base