Docs: Record definition style

Created on 1 Aug 2018  Â·  15Comments  Â·  Source: dotnet/docs

There are at least 3 ways to define a record:

type Record =
  { clients: int
    field: string }
    member x.MyField = x.field
type Record =
    { clients: int
      field: string }
    member x.MyField = x.field
type Record = {
    clients: int
    field: string 
} with
    member x.MyField = x.field
type Record =
    {
        clients: int
        field: string 
    }
    member x.MyField = x.field

If we cann't recommend a particular style (because people do it differently) we should at least list the common ones to help new-comers (and list advantages and disadvantages...


Document Details

⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

Area - F# Guide

Most helpful comment

type Record =
  { Clients: int
    Field: string }
  member x.MyField = x.field

All 15 comments

The current guidance does not enumerate the various ways to define records, though I'd be open to a PR that does lay out a few of these other styles.

@cartermp Should we discuss and decide on one of the above with some people or just list those three (personally, I don't really like all of them) ?

type Record =
  { Clients: int
    Field: string }
  member x.MyField = x.field

The problem is none of them have a particularly nice line up between the end of definition and a member. Having the requirement to use { } seems odd.

@7sharp9 Note that while I completely agree with you that any of the styles "feel" awkward this issue is not really about that. What I'm asking for is: What do we suggest newcomers to use considering the current state of the language.

I think your comment should be a language suggestion or discussed with @dsyme directly ;)

@vasily-kirichenko Now I realize that your suggestion is slightly different:

type Record =
<indent  >{ Clients: int
<indent+2>Field: string }
<indent  >member x.MyField = x.field

vs

type Record =
<indent-2>{ Clients: int
<indent  >Field: string }
<indent  >member x.MyField = x.field

which was my suggestion. It seems your suggestion is also what the compiler uses and looks quite good. Maybe we should just go with that?

@matthid I totally agree :)

I use the same style that @vasily-kirichenko does.

One thing to keep in mind about using what the compiler does is documented here: #5552

TL;DR, for beginners who don't know how to please the compiler with indent/outdent rules, this is the best way to do it without getting yelled at by an IDE:

type MyRecord =
    {
        SomeField : int
    }
    interface IMyInterface

@vasily-kirichenko's suggestion is what you'll likely find the most online, which is a virtue. But so is recommending something that is as resilient as possible. The current section shows neither, so I think either of these is an improvement.

@cartermp Yes good feedback and indeed something we want to fix. The syntax you suggest seems the most F# "untypical" of all the suggestions to me as it uses a lot of "blank lines" and noise. Shouldn't we try to improve our tooling instead?

We could also go:

type Record =
    {   clients: int
        field: string }
    member x.MyField = x.field
type Record =
<i  >{<i-1>clients: int
<i  ><i   >field: string }
<i  >member x.MyField = x.field

which I guess would fix this problem as well. But this is never seen anywhere at the moment (or at least I have never seen it).

3 means cleaner git diffs while saving vertical space and having simpler horizontal spacing.

In my experience, only two forms work "at scale": the one @vasily-kirichenko suggests (my personal favorite) and the 3rd choice from the original listing. I'd vote for either of those. Note, also, @vasily-kirichenko suggestion works best for _record instances_ (in case having symmetry between definition and instantiation is important).

3's instances are consistent:

let empty = {
    Field1 = 1
    Field2 = "hi"
}

can also be consistent with list / array style:

div [
    firstThing prop1 [
        innerThing prop2 prop3
        inneIinnerThing prop4 prop5 [
            deepThing noProp
        ]
    ]
    secondThing prop6 [
        lastThing prop7 prop8
    ]
] 

as the first can:

div
  [ firstThing prop1
      [ innerThing prop2 prop3
        innerThing prop4 prop5
          [ deepThing noProp  ]  ]
    secondThing prop6
      [ lastThing prop7 prop8  ]  ]

Added a suggestion PR https://github.com/dotnet/docs/pull/6956, which tries to capture this discussion

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stjepan picture stjepan  Â·  3Comments

ite-klass picture ite-klass  Â·  3Comments

svick picture svick  Â·  3Comments

stanuku picture stanuku  Â·  3Comments

FrancescoBonizzi picture FrancescoBonizzi  Â·  3Comments