-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Field update syntax for Records #1049
Comments
An alternative could be:
Of course for short fields name, the advantage is small, but for long Domain related field names, its quickly a win. |
I actually like the |
That would be neat. Like if it's a tuple:
And it could even be partial (to make it simpler than suggestion with yields) :
Property keeps same value if it doesn't match.
Just keeps empty list as is. |
Treating it as a nested pattern, interesting |
The general pattern would be:
Translated to:
When matchExpr is total, the _ clause is dead code and can be discarded. And, in a way, the classic syntax would be equivalent to:
|
The longer I look at this, the more I think it's a very worthwhile bit of sugar. 💯 |
It can also play nicely with my suggestion on conditional updates #1016 |
Yes, I think the syntax here is close to what already exists.
|
The version with 'as' is nice also but a bit longer. |
@thinkbeforecoding The |
Yes, and an extra keyword is not necessary since there is no ambiguity. |
Thinking about beginners I think the |
Yes the idea is to just bind a name to the value. So that it is not a special syntax, in f#, you can already write things like
And
is just a special case of it, catch-all matching with a name. So there is no irregularity here, just the possibility to bind the value of the field to use it in the expression. |
I see your point but consider someone in the future being annoyed by |
The stated advantage is "simpler code for immutable constructs". Actually "shorter, but more complex and obfuscated" is more accurate. Take the snippets posted: let add value avg =
{ avg with
Total = avg.Total + value
Count = avg.Count + 1 }
let add value avg =
{ avg with
Total t = t + value
Count c = c + 1 } In both cases you have The second snippet has syntax If you try to regularize this then it becomes In general the there is no need for syntactic sugar for expressions of the type |
Another idea could be generating lenses for record types in fsc with get/set/update functionality. We would even have a syntax for these, since old
|> MyRecord.Field .= newValue
|> MyRecord.Other.Update(fun a -> a + 1) What do you think? (Details to be worked out) |
For context, lenses suggestion was here #379 @charlesroddie How do you feel about the
|
As proposed before, using 'as' this could be a pattern on the right, like already possible in match since last version. |
Addition of A more logical syntax (which I still don't support as it's not needed) would be |
Overall wouldn't it just be cleaner to have some syntax for applying functions to record fields?
Of course one would need to come up with a more suitable operator and I'm still not convinced that this would really improve things, however it would make use of existing constructs (functions, update-syntax, operators) |
Or maybe something like this would make it clearer that it's the old value being transformed, without introducing a new operator. let add value avg =
{ avg with
Total as t -> t + value
Count as c -> c + 1 } (with or without |
Possible to consider new keyword to emphasize the binding is not representing the actual updated field?
|
{ avg with
Total t <- t + value
Count c <- c + 1 } If we use the assignment operator |
The main benefit I see here is that you wouldn't get a chance to reference a different field or an unrelated value (of the same type) on the right hand side by accident. Copying update lines and then manually changing field names is especially prone to this, but you could make the same mistake while typing out the update as usual - @Happypig375, nice idea, but someone could then go 'Why can't I also write @Tarmil, I quite liked your suggestion too, because it's reminiscent of a match clause. Therein also lies the problem the more I look at it. |
@kerams We could also allow that, but creates two ways of doing to same thing. |
I disagree, now it looks like you're mutating the original record. |
|
But that's the point, this syntax sends mixed signals. |
Good point, |
Thank you for this suggestion. I've taken a look at this and discussed with @vzarytovskii and will close this as something we're not going to do. The feature doesn't occur in other languages with record syntax, and the specific choice to allow naming of the |
Field update syntax for record
I propose we implement an update syntax for records. We can update records using the { x with .. } syntax, but it is quickly quite verbose.
I propose the following syntax:
This is especially convenient when dealing with nested records and the RFC https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1049-nested-record-field--copy-and-update-expression.md :
The existing way of approaching this problem in F# is to access the field from the input object:
Pros and Cons
The advantages of making this adjustment to F# are simpler code for immutable constructs.. reduce the temptation to use lenses 😁
The disadvantages of making this adjustment to F# are a new syntax, added complexity in the compiler
Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Related suggestions:
https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1049-nested-record-field--copy-and-update-expression.md
Affidavit (please submit!)
Please tick this 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 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.
The text was updated successfully, but these errors were encountered: