I'm not a fan of the new syntax for struct tuples, struct records, and struct unions. I feel like it could have been avoided with a lesser evil if they had followed the same approach that Scala is using for anonymous functions in the upgrade to 2.12.
Specifically, don't introduce new syntax, but force your users to deal with the fact that your bytecode is now incompatible with previous versions and now requires a new minimum version for the VM. They can recompile...it's not really that big of a deal. It is far more of a big deal to rewrite all of your code than it is to upgrade your VM and recompile.
Considering the two existing ways to defines structs are
type S = struct val X:int end
type [<Struct>] R = val Y:int
it's not new syntax as much as an extension of the contexts where the construct is applicable.
The examples in the blog post aren't in accordance with the RFC as far as type signatures are concerned [1] The tuple decomposition is mixed in with the type sig.
I definitely agree with you for tuples especially smaller tuples. As tuples get larger however performance can swing the other way. As someone who codes some F# for my day job it seems that while tuples should be easier in a functional language like F# for backwards compatibility struct tuples will be more awkward to use than in C# 7. I think they should of just bit the bullet for tuples up to a certain size.
For records and unions however I think the attribute is fine. Most of the time for types of more than 3 fields say structs can be worse in performance than classes anyway. Records and unions tend to be assigned more and live longer than tuples most of the time. For unions for obvious reasons structs are not recursive in nature which with unions is required somewhat (see https://msdn.microsoft.com/en-us/library/ms229017%28v=vs.110...). Definitely wouldn't want structs to be the default here.
This tuple stuff is a mess. From the RFC:
>This is based partly on the assumption that the proposed C# 7.0 tuples will use struct representations for at least some small tuple types.
This is what F# had to begin with! They were sort of pushed into using a heap-allocated type via System.Tuple, in the name of compatibility with the rest of .NET. Frustrating!
It's also sad to see no mention of really improved tooling, to put F# on the level of C#. MSCorp paid some lip service, well overdue since the F# guys are the ones that gave them generics which was the biggest thing technical advancement .NET had over Java.
> It's also sad to see no mention of really improved tooling, to put F# on the level of C#.
Could you clarify what you mean here? Perhaps I could have written more about it in the blog post, but sitting the language service atop the Roslyn Workspace layer is critical work that:
1. Gives F# a "modern" editor experience out of the box.
2. Gives F# an entry point into the large amount of Roslyn-based IDE features. Workspaces are how they "talk" to the language, so that means that they can now "talk" to F# as well. This is not possible with tooling today.
Hmm, how much does this provide? Will this make, say, F# interactive competitive with C# interactive? (Which blew past it, despite F#'s near-decade lead.)
Hearing this in the context of Scala is hilarious[0].
> force your users to deal with the fact that your bytecode is now incompatible with previous versions and now requires a new minimum version for the VM. They can recompile...it's not really that big of a deal.
Only in the ideal world of greenfield development. You have to ensure that the build system, bytecode enhancer, AOP injectors all are able to cope with the new bytecode format.
I actually wish a keyword was also usable for the case of reference type tuples in order to be able to disambiguate those in libraries and later switch the default.
It seems the feature was implemented to answer the concern of interop with C# (which in future v7 will have shorthand syntax only for System.ValueTuple but not for System.Tuple), the language might later add better support for deconstruction without the extra keyword.
For tuples which remain local, the compiler is generally good at eliding those (but not in all cases, if it is a concern, always check the optimized compiled output).
Specifically, don't introduce new syntax, but force your users to deal with the fact that your bytecode is now incompatible with previous versions and now requires a new minimum version for the VM. They can recompile...it's not really that big of a deal. It is far more of a big deal to rewrite all of your code than it is to upgrade your VM and recompile.