fsharp / fslang-suggestions

The place to make suggestions, discuss and vote on F# language and core library features
345 stars 21 forks source link

Symplify `val mutable` with user specified default value definition #1321

Open konst-sh opened 1 year ago

konst-sh commented 1 year ago

**I propose we allow to omit [<DefaultValue>] attribute and specify the value itself on val mutable property

**The existing way of approaching this problem in F# is to stick with types default values and create additional constructor that will override them to what you actually need.

Here is my example - the aim is to safely define pretty large DTO type with meaningful defaults, as the number of fields is significant I was looking for the way to not duplicate them in constructor, so member val syntax was looking good enough. Then I found that to be able to specify property value in constructor directly it either requires to define properties as mutable with with get, set or define property with [] attribute - but that wouldn't allow to specify concrete default value. So here is my current implementation:

type TranslationSpec (elementId: string, formatName: string) =
    member val allowFaultyParts: bool option = None with get, set
    member val angularTolerance: float option = None with get, set
    member val formatName: string = formatName with get, set
   //^^^ around 70 properties in total

And here is the proposed:

type TranslationSpec (elementId: string, formatName: string) =
    val mutable allowFaultyParts: bool option = None
    val mutable angularTolerance: float option = None
    val mutable formatName = formatName
   // and so on

Pros and Cons

**The advantages of making this adjustment to F# is far less boilerplate

**The disadvantages of making this adjustment to F# is - more variability in class definition

Extra information

**Estimated cost (XS, S, M, L, XL, XXL): M

**Related suggestions: #722 I would say it should be somehow related to records construction as member val fields are pretty much similar to what record fields providing, If only we had user specified default value capability for records without creating constructor method and duplicating all the field names again and then had auto-generated constructor with ability to override only certain fields.

possible way to specify record field defaults without additional constructor boilerplate method:

type TranslationSpec = {
    allowFaultyParts: bool option = None
    angularTolerance: float option = None
    formatName = Some "STEP" //here we can have inferred field type `string option`
    someFieldWithoutDefault: string
}
//and then it will be possible to:
let ts = TranslationSpec(someFieldWithoutDefault = "someValue")

the above syntax would mean that when record constructor will be exposed it will treat field with default values as optional and without them - as required.

Affidavit (please submit!)

Please tick these items by placing a cross in the box:

Please tick all that apply:

For Readers

If you would like to see this issue implemented, please click the :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.

bartelink commented 1 year ago

Please take the time to fix the formatting!