-
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
Support for F# record syntaxes for C# defined records #1138
Comments
It sounds reasonable to me, and should be straightforward as long as the scope is only about the It will, however, get complicated, if we want full compatibility, such as "converting" C# records to F# ones and vice versa, we will need to deal with the inheritance, IL representation, etc then. It makes sense from the language perspective to support it, especially for new users, @dsyme wdyt? |
@vzarytovskii, thanks! I probably miss other features in the top bullet list that need to be considered, but could you expand on what you mean about "converting" as I am not sure which feature or aspect it relates to, I kind of connect it to the way anonymous records can be extended by adding properties, making a new type. Is it this particular area of the language? I am personally ok with limiting the feature scope to what is easiest to tackle, if it allows to cover what felt most needed in the initial list I've put. This request is not about supporting inheritance of F# records, but I see that consuming the C# ones involves complexity related to records possibly forming a hierarchy. |
I'm inclined not to do "type inference on record field names" for C# record types. My initial thought is not do "record constructor syntax { X = 1; Y = 2 }" for C# record types either. The construction syntax for C# records is I'm in two minds about "copy-and-update". Let's assume construction syntax for C# records is That said, it's not a huge problem if we support
|
As an aside, just noting a technical matter: For type R<'T> = { X : 'T; Id: string }
let r1 = { X = 1; Id = "a" } // R<int>
{r1 with X = "one" } // doesn't become a R<string>, instead an error is given. Because of the way C# compiles From the PL design perspective in theory this could become a different type, but in F# and OCaml it doesn't. F# does allow this for anonymous records: let r1 = {| X = 1; Id = "a" |} // {| X: int; Id: string |}
{| r1 with X = "one" |} // {| X: string; Id: string |} |
There's another question whether C# records can be used as inputs to anonymous record syntax, e.g.
F# records can be used as inputs to anonymous records. So this should be possible for C# records too: type R = { X : int; Id: string }
let r1 = { X = 1; Id = "a" } // R<int>
{| r1 with X = "one" |} |
@dsyme, a minor comment on
I think Ideally, it should turn into record initialiser syntax proper, and other syntaxes should give warnings asking to use that syntax only. Based on discussion on the C# co-thread (not gonna happen, unless F# code gen adjusts), the underlying code-gen for C# records would need to use the same All points you give and that were made on the C# co-thread are great insight of the subtleties into supporting this. |
I think it's due to C# records generating the appropriate constructor (for positional properties only).
I guess this is one the controversial things, whether we want F# record syntax for C# records.
Maybe I'm mistaken about what you mean here, but if i understood it correctly - i think generating Clone for F# records (to have them compatible with C# with syntax) is a reasonable thing to do. |
My understanding is that these are positional parameters in C#, and so positional invocation is ok. Named properties in C# are
I'm not sure about this. Record syntax in F# is not particularly natural particularly for the positional parameters. For things combining positional and named the constructor syntax is already well set up and working well. |
Yes, we can generate |
To me, similar construct should flow simply, with niceties / idioms of the language they are consumed from, giving the "compiler is your friend" and "language is simple" feel. True, they are positional in C#, but since F# doesn't allow usage of positional parameter for construction of F# defined records, it really should not encourage it for C# defined records, IMO. Now, if I read @dsyme comments properly, it assumes that F# will distinguish C# records and expose
This will make C# enable the Overall, isn't it keeping F# simpler, if records still look like records, no matter which language it is defined in? with minor caveats for things that can be considered side cases (polymorphism due to inheritance and generic).
This may be a separate suggestion, and of course, mandated by F# adopting the initializer syntax and discouraging the positional constructor argument one. What, overall, makes it important / better to keep distinction? It feels with what @dsyme proposes, it would make consumption of F# and C# defined records in C# natural, and make consumption of records not defined in F# a bit alien in F#, with more "object" feel than seems required to me. Just trying to understand better the motives, and having better code gen for F# records to be consumed in C# is nice move. |
Another point to consider is pattern matching, which has special syntax support in F#. Related: #968, caveat: #968 (comment)
|
I propose we add support to F# language for
{ myRecord with ... }
{ X = 1; Y = 2 }
to C# defined record types.
Pros
Cons
Extra information
Estimated cost: M
Related suggestions:
dotnet/fsharp#13007 (comment) (C# X support in F# Y issue)
dotnet/csharplang#6067 (co issue for C# compiler, discussions revolves around F# adjusting code generation for F# records to make it look like what C# compiler expects)
The text was updated successfully, but these errors were encountered: