diff --git a/RFCs/FS-1049-nested-record-field--copy-and-update-expression.md b/RFCs/FS-1049-nested-record-field--copy-and-update-expression.md index 94176bd8..145a9a0e 100644 --- a/RFCs/FS-1049-nested-record-field--copy-and-update-expression.md +++ b/RFCs/FS-1049-nested-record-field--copy-and-update-expression.md @@ -17,7 +17,7 @@ Enable updating nested record field with "with" syntax. # Motivation [motivation]: #motivation -This improves readability. In cases where need to update the value of a nested field in record. +This improves readability in cases where nested record field values need to be updated. For example, take the following code: @@ -25,26 +25,71 @@ For example, take the following code: type Street = { N: string } type Address = { S: Street } type Person = { A: Address; Age: int } -​ + let person = { A = { S = { N = "Street 1" } }; Age = 30 } -​ + let anotherPerson = { person with A = { person.A with S = { person.A.S with N = person.A.S.N + ", k.2" } } } -​ + let anotherPerson1 = { person with A.S.N = person.A.S.N + ", k.2" } ``` # Detailed design [design]: #detailed-design -Carefully transform the ast in TypeChecker.fs to expand to the current form -Need to consider in some cases -1. Handle the possible ambiguity of specifing type name vs field name +Transform the AST in TypeChecker.fs to expand the new syntax into the current form. + +````fsharp +let anotherPerson = { person with A.S.N = person.A.S.N + ", k.2" } +```` + +Becomes: + +````fsharp +let anotherPerson = { person with A = { person.A with S = { person.A.S with N = person.A.S.N + ", k.2" } } } +```` + +Need to consider: + +1. Handle the possible ambiguity of specifying type name vs field name 2. Group nested field from the same parent -3. All nested field parts need to be decleard on record type +3. All nested field parts need to be declared on record type 4. Collaborate with anonymous records feature 5. Check IntelliSense 6. Investigate other language features that should support nested paths like named arguments -7. Check no same nested field update +7. Check same field is not updated twice within statement + +## Syntax + +This change allows updating nested fields, using dot notation, within one copy and update statement. + +````fsharp +let anotherPerson = { person with A.S.N = "1" } +```` + +Multiple fields with differing levels of nesting can be updated within the same expersssion. + +````fsharp +let anotherPerson = { person with A.S.N = "1"; Age = 1; } +```` + +Fields can be accessed through Namespace, Module or Type name. + +The implementation expands the nested syntax into the existing AST for nested updates so qualified access is checked through the same mechanism. + +__TypeName Access__ +````fsharp +let anotherPerson = { Person.A.S.N = "1"; Person.Age = 1; } +```` + +__ModuleOrNamespaceName Access__ +````fsharp +let anotherPerson = { ModuleOrNamespaceName.A.S.N = "1"} +```` + +__ModuleOrNamespaceName.TypeName Access__ +````fsharp +let anotherPerson = { ModuleOrNamespaceName.Person.A.S.N = "1" } +```` # Drawbacks [drawbacks]: #drawbacks @@ -56,34 +101,38 @@ Additional complexity in the compiler. This is not a breaking change, and is backwards-compatible with existing code. -# Open Questoions +# Open Questions Q: What about indexers, e.g. -``` +```fsharp let anotherPerson1 = { person with A.[3].N = person.A.[3].N + ", k.2" } ``` -A:Need to look at it +A: Need to look at it Q: What happens to cases where A.S is mentioned twice? -``` +```fsharp { person with A.S.N = person.A.S.N + ", k.2"; A.S.M = person.A.S.M + ", k.3" } ``` A: Already implemented will compile to -``` +```fsharp { person with A = { person.A with S = { person.A.S with N = person.A.S.N + ", k.2"; M = person.A.S.M + ", k.3" } ``` Q: What about similar features in the language that name fields, especially mutating property setters -``` +```fsharp Person(A.C.N = 3, A.C.M = 4) ``` A: Need to look at it after we finish with the records +Q: [_Will it work with struct records without introducing lot's of struct copy?_](https://github.com/Microsoft/visualfsharp/pull/4511#issuecomment-401640471) + +A: The current implementation is expanding the simplified AST into the existing one and will have the same struct copy issue mentioned by @zpodlovics. However, as this issue is present in the original copy and update expression this would have to be fixed as well as updating the new implementation. This will be investigated further once the open tasks are completed. + # Alternatives - Do not implement this feature