> In this Artima interview from the JVM Languages Summit,
> Rich Hickey, the creator of the Clojure programming
> language, discusses his perspective on mutable state and
> what programming languages should do about it.
>
> Read this Artima.com interview:
>
>
http://www.artima.com/articles/hickey_on_time.html>
> What is your opinion of Hickey's notion that the problems
> people usually associate with mutable state are problems
> of time? What do you think of the idea that you should
> write as much of your program as possible with immutable
> objects (or data) and pure functions?
I think the Pure Functional Programming people are leaving in a fantasy land. They speak about Pure FP as if it makes it impossible to introduce bugs, which, of course, it's not the case at all. They blame the concept of "state" for everything, which is absurd, to say the least. Their programs are full of monadic type declarations, since almost everything requires state, and when they are asked to produce a quicksort implementation that is as fast as in-place quicksort, or when they are asked to solve the problem of tree (parent points to child, child points to parent), they mumble something about some very strange patterns (they call it the zip pattern or something like that) that requires you to interleave your code (whatever that is: a calculation, event management in a gui app, packet reception from the network) with the tree manipulation structure, resulting in a big spaghetti mess.
The advantages of functional programming include the strong and static type system and the functions as first class entities. Pureness is a straitjacket and a severe disadvantage.
Here is an example of the madness (quote taken from the article):
A large system that's a graph of mutable objects is just very hard to understand.And in Pure FP, a large computation that's a graph of function calls is also very hard to understand. The wrong values appear at function parameters instead of object members. There is no difference in reality between objects that are inconsistent internally and functions with wrong parameters. In Pure FP, the problem of wrong values is transferred from objects to functions.
The real issue behind programming is not time or pureness or immutability.
First of all, there is no such thing as an impure function, unless the function reads some value from the hardware. Each and every procedure/function/subroutine/calculation in a program will give the exact same result, if given the exact same parameters. And by parameters, I mean not only the values passed to it, but implicit parameters like global variables. External variables to a function are input variables to the function as well. Given a function F and and input I, where I is P (parameters passed to the function) and G (variables accessible in the context of F), the output is always O:
I = {P, G}
F(I) = O
The real issue in programming is partial functions. Most, if not all, programming functions, allow for partial functions, i.e. for functions where not all the possible values of the input are mapped to a result.
For example (to take an example from the article), A Date object is inconsistent because of violation of the mathematical function that defines the date. When we have month = February and then we set the day = 31, we have violated the definition of Date. There is no date February, 31. It's not a problem of time, it's a problem of partiality: at that specific point of computation, we have violated the definition of Date.
The problem of partial functions extends to everything. For example, the function 'fclose' is defined as a function that takes as input an open file, not a closed one. But there is no check from the compiler if we pass a closed file or not.
Another example is functions that do not accept null pointers. The input set of such a function does not include the null value, but the compiler does not complain. FP languages somewhat address the problem by using Maybe types, but the solution does not cover the whole range of problems. For example, it's not possible to say that the input pointer for a function can take values within the range X..Y.
One solution to the problem of partial functions is to make values as types. A range type from X to Y, for example, can only statically accept a value that is within the range; at run time, if we have a value that may be out of range, we statically promote the value to the X..Y if the value is inside the range, and we declare an alternative action when the value is outside of the range. For example (in C++ parlance):
int main() {
int i;
//input of arbitrary value
cin >> i;
//new construct: match i within a range;
match (i => range<10, 20>) {
//from now on, the type of i is 'range<10, 20>', not 'int'.
//we can access an array's members without bounds checking.
array<int, 10, 20> data;
data[i] = 5;
}
otherwise {
//value out of range.
}
}
Incidentally, using values as types allows for a lot of optimizations; for example, in the above, bounds checking is redundant.
I apologize for the long reply, but some things need to be said, in my opinion. It ticks me off when I see people can't recognize the real nature of the problem in programming :-).