Of course, I'm not so daft as to say that, but:
If you use an imperative programming language that provides for mutable state, that's what you are saying.
For some background, I read this article
yesterday, which contains this choice passage (emphasis mine):
Imagine you've implemented a large program in a purely functional way. All the data is properly threaded in and out of functions, and there are no truly destructive updates to speak of. Now pick the two lowest-level and most isolated functions in the entire codebase. They're used all over the place, but are never called from the same modules. Now make these dependent on each other: function A behaves differently depending on the number of times function B has been called and vice-versa.
In C, this is easy! It can be done quickly and cleanly by adding some global variables. In purely functional code, this is somewhere between a major rearchitecting of the data flow and hopeless.
A comment on proggit
very concisely summed up just how crazy the above passage is:
Considering that one of the majors reasons to use FP is so that you don't have such inter-dependencies, it's odd to point that out as an issue.
The whole problem with imperative programming is that state gets threaded everywhere, and you can't look at any function individually and know how it will behave. I won't even go into problems associated with concurrency, where state becomes incredibly difficult to reason about if you allow that sort of thing.
I really appreciated the notion of imperative programming "threading state everywhere". Let's drive the point home, though.
Hey, I'm just the messenger
Consider a method you might see in any Java application (I oh-so-love the jvm, so I get to pick on Java), but the same sort of thing applies in C, C++, C#, python, ruby, perl, et al.:
[sourcecode language="java"]public void doSomething (String arg1, int arg2, FooBar arg3) throws IOException;[/sourcecode]
Simple enough, right? Hey, we're programming, life is good. But, what if you saw a signature like this:
[sourcecode language="java"]public void doSomething (String arg1, int arg2, FooBar arg3, .....,
String arg316) throws IOException;[/sourcecode]
316 arguments to a method (which I don't think is actually possible in the jvm, but bear with me)? "That's absurd!", you'd say. The problem, of course, is that the 3-arg
actually has far more arguments than its signature implies:
The behaviour of every function in a mutable, imperative environment is dependent upon the state of all of the other (variables|attributes|bindings|whatever) in your program at the time the function is invoked.
So, if you have 313 other variables in your program, that 3-arg
is functionally (ha!) operating over 316 arguments.
Would you ever intentionally write a method signature that takes 316 arguments? Would you use any library that contained such a function signature? No? Then why are you using tools that force such craziness upon you?
Of course, there is a place for mutable, imperative programming.
The fellow who wrote the blog post to which I linked above appears to work on games, one of the few places where one could unapologetically use an imperative programming language with mutable state. Update
: Looks like the state-of-the-art in game programming is heading towards FP languages more than I thought. Thanks to this comment
, here's a LtU thread
, with slides, about the guys who wrote Gears of War and the Unreal engine recommending FP as the future of game development.
However, we need to collectively get past encouraging other software developers – the vast majority of whom do not have the particular requirements of game, systems, or embedded development – to inflict the pain of imperative languages and mutable state upon themselves, especially given the concurrency challenges that lie ahead (never mind the general problems such environments present, as I argue above). The languages are ready
, the runtimes are widespread...let's stop doing it wrong.