In the wake of my "Why C# sucks" article, I've come to realize that there are real problems with the C-based, imperative-style languages I've learned (C++, Java, C#, Python, Javascript, etc). It's hard to pinpoint what because it's the only thing I've ever known, but dabbling in F# is giving me some savoury insights. I've rarely been this excited about a programming language, I feel like I'm about to learn an entire new way of thinking.
For now, what I'd like to mention is how the defaults in F# make more sense than in C#:
- Everything is immutable unless otherwise specified
- Nothing can ever be null except otherwise specified
- No function can call itself (even indirectly) unless you mark it as recursive
- All types are inferred from usage except in specific cases
Just the first 2 points are huge; I suspect that above 50% of all failures of all programs are caused by accidental mutation of variables and null references (Anders Hejlsberg once said that null reference exceptions alone caused 50% of failures). Just how many things can go wrong in the following code?
1) Every Point structure is mutable, so each point within the list can be changed before the foreach loop, potentially causing failure
2) The List itself is mutable: elements can be re-arranged, removed, inserted.
3) The pointList variable is mutable: it can be re-assigned to another list or even to null!
Each of these create state, which makes the program harder to reason about, to refactor (because order of statements matter) and to test.
To get immutability in C#, we have to be very disciplined and litter our code with "readonly" everywhere. This is not what the language encourages. The same effort would be required in F# to make things mutable, i.e. you have to explicitely confess your dirty intentions of creating state and potential points of failure in your program. I've never felt bad not writing readonly in C#: I can tell you that writing "mutable" in F# feels horrible every time (partly because it underlines my ignorance of functional programming - in a purely functional style, nothing needs to be mutable at all! Notably, Haskell has no mutable variables. None. F# is more forgiving to us sinners).
I'm currently reading Real-World Functional Programming and writing a Tetris game with XNA and F#, just to get the hang of the syntax. My program has an aweful lot of "mutable" keywords in it, but it still looks prettier, safer and more declarative than anything I've written in C# already. I'm looking forward to mastering the language and hopefully eliminating the need for C# most of the time (I'm sure C# does certain things better than F# - haven't figured out what yet though
).
P.S.: because it's fun, the above program in F#:
For now, what I'd like to mention is how the defaults in F# make more sense than in C#:
- Everything is immutable unless otherwise specified
- Nothing can ever be null except otherwise specified
- No function can call itself (even indirectly) unless you mark it as recursive
- All types are inferred from usage except in specific cases
Just the first 2 points are huge; I suspect that above 50% of all failures of all programs are caused by accidental mutation of variables and null references (Anders Hejlsberg once said that null reference exceptions alone caused 50% of failures). Just how many things can go wrong in the following code?
struct Point {
public int X { get; set; }
public int Y { get; set; }
}
(...)
List<Point> pointList = getPoints();
(...)
foreach(var point in pointList) {
// do something with points assuming they are what was returned by getPoints
}
We have mutability at 3 levels here:1) Every Point structure is mutable, so each point within the list can be changed before the foreach loop, potentially causing failure
2) The List itself is mutable: elements can be re-arranged, removed, inserted.
3) The pointList variable is mutable: it can be re-assigned to another list or even to null!
Each of these create state, which makes the program harder to reason about, to refactor (because order of statements matter) and to test.
To get immutability in C#, we have to be very disciplined and litter our code with "readonly" everywhere. This is not what the language encourages. The same effort would be required in F# to make things mutable, i.e. you have to explicitely confess your dirty intentions of creating state and potential points of failure in your program. I've never felt bad not writing readonly in C#: I can tell you that writing "mutable" in F# feels horrible every time (partly because it underlines my ignorance of functional programming - in a purely functional style, nothing needs to be mutable at all! Notably, Haskell has no mutable variables. None. F# is more forgiving to us sinners).
I'm currently reading Real-World Functional Programming and writing a Tetris game with XNA and F#, just to get the hang of the syntax. My program has an aweful lot of "mutable" keywords in it, but it still looks prettier, safer and more declarative than anything I've written in C# already. I'm looking forward to mastering the language and hopefully eliminating the need for C# most of the time (I'm sure C# does certain things better than F# - haven't figured out what yet though
P.S.: because it's fun, the above program in F#:
type Point = {
X : int
Y : int
}
(...)
let pointList = getPoints() // where getPoints() typically returns a seq<Point>, i.e. IEnumerable<Point>
(...)
for point in pointList do
// do something with points KNOWING it's the same points that were returned by getPoints
// I like knowing better than assuming :)







Unless a restriction really helps to prevent bugs, I think the most common behavior should be default (to a point, of course). Recursive functions are much less common, so I would be fine with non-recursive by default.
On another note, I think function arguments could be readonly by default. Depending on the input, you're unlikely to change it, and accidentally modifying a function argument could cause unexpected changes outside of the function. Sometimes, I'll purposely use function parameters instead of declaring a local variable, simply to optimize my code.
I think other programming languages can learn from the functional paradigm, but it's a style of programming I wouldn't want to use on a daily basis.
P.S. I love these posts, keep them coming!