C# will eventually get all F# features, right? by Mark Seemann
C# will never get the important features that F# has. Here's why.
The relationship between C# and F# is interesting, no matter if you look at it from the C# or the F# perspective:
- Before releasing F# to the world, Don Syme, its inventor, was instrumental in getting generics into C# and .NET. Had it not been for his and his Cambridge colleagues' effort, we wouldn't have generics today, or we would have the subpar generics that Java has. (Okay, so this point isn't strictly about F#.)
- F# has had async workflows since 2007. In F#, this is simply one of many implementations of a more general language feature called Computation Expressions - other common examples are Sequence Expressions and Query Expressions, but you can also create your own. When async/await was added to C# in 2012, it was a port of that particular implementation, but turned into a one-shot language feature.
- C# 6 gets a lot of small language features, some of which F# already has: auto-property initializers, exception filters, expression-bodied function members...
- For C# 7, the design team is considering many Functional language features that F# already has: pattern matching, records, immutability, tuples...
It's not some hidden cabal that I'm trying to expose, either. Mads Torgersen has been quite open about this relationship.
Why care about F#, then? #
A common reaction to all of this seems to be that if C# eventually gets all the best F# features, there's no reason to care about F#. Just stick with C#, and get those features in the future.
The most obvious answer to such statements is that F# already has those features, while you'll have to wait for a long time to get them in C#. While C# 6 gets a few features, they are hardly killer features. So perhaps you'll get the good F# features in C#, but they could be years away, and some features might be postponed to later versions again.
In my experience, that argument mostly falls on deaf ears. Many programmers are content to wait, perhaps because they feel that the language choice is out of their hands anyway.
What F# features could C# get? #
Often, when F# enthusiasts attempt to sell the language to other programmers, they have a long list of language features that F# has, and that (e.g.) C# doesn't have. However, in the future, C# could hypothetically have those features too:
- Records. C# could have those as well, and they're being considered for C# 7. Implementation-wise, F# records compile to immutable classes anyway.
- Discriminated Unions. Nothing in principle prevents C# from getting those. After all, F# Discriminated Unions compile to a class hierarchy.
- Pattern matching Also being considered for C# 7.
- No nulls. It's a common myth that F# doesn't have nulls. It does. It's even a keyword. It's true that F# doesn't allow its Functional data types (records, unions, tuples, etc.) to have null values, but it's only a compiler trick. At run-time, these types can have null values too, and you can provide null values via Reflection. C# could get such a compiler trick as well.
- Immutability. F#'s immutability 'feature' is similar to how it deals with nulls. Lots of F# can be mutable (everything that interacts with C# code), but the special Functional data types can't. Again, it's mostly in how these specific data types are implemented under the hood that provides this feature, and C# could get that as well.
- Options. These are really just specialised Discriminated Unions, so C# could get those too.
- Object Expressions. Java has had those for years, so there's no reason C# couldn't get them as well.
- Partial Function Application. You can already do this in C# today, but the syntax for it is really awkward. Thus, there's no technical reason C# can't have that, but the C# language designers would have to come up with a better syntax.
- Scripting. F# is great for scripting, but as the success of scriptcs has shown, nothing prevents C# from being a scripting language either.
- REPL. A REPL is a really nice tool, but scriptcs already comes with a REPL, again demonstrating that C# could have that too.
What F# features can C# never get? #
There are a few F# features that many people point to as their favourite, that C# is unlikely to get. A couple of them are:
- Type Providers. Someone that I completely trust on this issue told me quite authoritatively that "C# will never get Type Providers", and then laughed quietly. While I don't know enough about the technical details of Type Providers to be able to evaluate that statement, I trust this person completely on this issue.
- Units of Measure. Here, I simply have to confess ignorance. While I haven't seen talk about units of measure for C#, I have no idea whether it's doable or not.
In a recent article, I explained how less is more when it comes to language features. Many languages come with redundant features (often for historical reasons), but the fewer redundant features a language has, the better.
The F# compiler doesn't allow circular dependencies. You can't use a type or a function before you've defined it. This may seem like a restriction, but is perhaps the most important quality of F#. Cyclic dependencies are closely correlated with coupling, and coupling is the deadliest maintainability killer of code bases.
In C# and most other languages, you can define dependency cycles, and the compiler makes it easy for you. In F#, the compiler makes it impossible.
Studies show that F# projects have fewer and smaller cycles, and that there are types of cycles (motifs) you don't see at all in F# code bases.
The F# compiler protects you from making cycles. C# will never be able to do that, because it would be a massive breaking change: if the C# compiler was changed to protect you as well, most existing C# code wouldn't be able to compile.
Microsoft has never been in the habit of introducing breaking changes, so I'm quite convinced that this will never happen.
Summary #
C# could, theoretically, get a lot of the features that F# has, but not the 'feature' that really matters: protection against coupling. Since coupling is one of the most common reasons for code rot, this is one of the most compelling reasons to switch to F# today.
F# is a great language, not only because of the features it has, but even more so because if the undesirable traits it doesn't have.
Comments
I would say C# won't get non-nullable reference types either, even in the form of a compiler trick. It would either introduce too much of breaking changes or be very limited and thus not especially usefull.
Vladimir, thank you for writing. You're probably correct. Many years ago, I overheard Anders Hejlsberg say that it wouldn't be possible to introduce non-nullable reference types into the .NET platform without massive breaking changes. I can't say I ever understood the reasoning behind this (nor was it ever explained to me), but when Anders Hejlsberg tells you that, you sort of have to accept it :)
FWIW, there's a bit of discussion about non-nullable reference types in the C# Design Meeting Notes for Jan 21, 2015, but I have to admit that I didn't follow the link to Eric Lippert's blog :$