Here is my view on F# after about two days of playing with it.
Disclaimer: I am just starting with F#. Some annoyances I talk about may be really insignificant for an experienced F# programmer. Others may be fixed in the future versions. Overall, I don’t totally reject the idea that F# might be the next best thing after the sliced bread. However, in my subjective view it is not ready for prime time, i.e. real large-scale commercial usage.
The good
* I like embedded parallelism.
* I like pattern matching.
* I like functional programming in general. I think it may go far, and elements of functional programming are in fact introduced lately in a non-functional languages like C#.
The bad
* The language is fairly large and it is not well-defined. Yes, we have F# manual, but compared to C# language specification it is of relatively low quality
* Since the language is large, even books don’t always do a good job in describing all corners. E.g. “Expert F#” book mentions such important (in my view) functional construct as Seq.unfold() exactly once, and without explaining what it is.
* F# does not leave a feeling of a cohesive language. Some things are too similar, to the point of confusion. E.g. what is the difference between LazyList
and seq
? When should I use one and when the other? Their APIs seem to be 90% identical. Or let me ask another question: what is the difference, if any, between ‘fun’ an ‘function’ keywords? Maybe you use the first one if you want the function to be funny? π
* F# has a tendency of inventing its own names for things. E.g. expression trees are ‘quotations’ and typedefs are ‘type abbreviations’. They also like to use weird terms like ‘derived constructors’ and ‘active data discriminant’. This does not help in learning the language.
* The imperative and functional paradigms are mixed (or rather separated) in funny ways. E.g. in C# I can realize a potentially infinite list of natural numbers by doing
IEnumerable<int> AllNumbers() { int n=0; while (true) yield ++n; }
I was not able to write an equivalent imperative-style code in F#. I was getting all kinds of things: “mutables cannot be used in ‘seq'”, “mutables cannot be used in closures”, “invalid left side of the assignment”, but most frequently, yes, of course – “syntax error”. Basically, it looks like imperative style cannot be used inside ‘seq’.
I was able to achieve the same effect only using the functional approach via “unfold” function:
let numbers =
Seq.unfold
(fun x -> Some(x, x+1)) 1
The Ugly
* Schizophrenic syntax. There are two modes: ‘light’ and default. Simply put, you are getting two slightly different languages for the price of one. It is like reading a book where some chapters are in Spanish and some are in Portuguese. The trouble is, the compiler is also bilingual. Sometimes it gets confused and complains about lack of Portuguese keywords in your Spanish sentences. E.g. at times I was getting errors such as there is no 'in' for this 'let'
while in light mode. Since ‘in’ keyword is normally not used in light mode, this error left me quite puzzled. I saw other people complaining about similar things.
* Vast majority of F# compiler diagnostics messages simply say “Syntax error”. This occurs even in relatively simple cases such as missing ‘->’ or ‘do’. I’ve seen better error detection in Pascal compilers on computers with 64K memory made 30 years ago.
* There are too many keywords. Some of them are quite cryptic, e.g. ->>, :?. Maybe they did it to reduce the program size, but if you go too far down that route, you get a write-only language like APL.
* Some of the keywords are ad hoc. E.g. you can use π to check for .NET types but not for F# types. There may be underlying reasons for that, but this is downright ugly.
* Poor tool support. F# is a paria language in .NET world and it will remain so for a long time. AFAIK, there is no form designer for F#. There is no Resharper for F#. There is no Reflector for F#. Et cetera, et cetera.
* Incompatibilities between versions. Since there is no language standard of any kind, we are at the complete mercy of the developers. I did hear people having problems compiling older code with new versions of F# compiler. And when most diagnostics messages are “syntax error”, it only compounds the problem.
Conclusion
I donβt think F# is ready for prime time yet. Before it can really be used, it needs to become more user friendly, more stable, more concise, and acquire more tools. If the functional paradigm seems to fit a part of a program really well, I would consider using F# for that part (and that part only) in F#, keeping overall amount of F# code as small as possible.
Permalink
LazyList is a purely functional data structure. Seq is based upon inherently mutable IEnumerators. Seq also supports custom code when opening and closing an enumeration.
For a mutable sequence of natural numbers use “ref” and “incr”.
You can use π for F# types as well as .NET types. You just need to call “box” first to turn it into an “obj”.
I’m happy there is no reflector for F# because it makes our commercial products harder to plagiarize!
Permalink
Also, the name “quotations” comes from Lisp and predates “expression trees” from C# by half a century, and the name “type abbreviation” comes from ML and predates C’s “typedef” by many years as well. So you cannot reasonably say that “F# has a tendency of inventing its own names for things”.
Permalink
I am writing from the point of view of C/C#/Java programmer. If, for example, you suddenly started to use the word “shura” instead of “line”, I would complain you invented your own name, and I would not be moved by the fact that the ancient Semitic word “shura” probably predates Middle English “line” by a couple of thousand years π
I won’t argue about Lisp, but with typedef you are probably wrong. According to Wikipedia C was created in 1972 and ML in 1973. Not that it really matters.