You are not set to an instance of an object
Monday, October 29th, 2007Today in school we had some exercises related to synchronization mechanism in Java. We grabbed the exercise descriptions and templates from the server and started coding. After five minutes the guy next to me started to yell why he gets a NullPointerException all the time and why eclipse’s jiangadeege-bulb doesn’t offer a fix for his problem.
We looked at it and some stack trace hopping later we got it fixed. After a while though, the guy on the right told me that he was experiencing the same problem (later we found out that there was an error in the provided template) and asked me to help him as well. I started to list the wonderful advantages of having functional languages and told them that most of those problems magically disappear in a language like Haskell. Some of the guys got it “cool”, this post is for the other ones.
Basically, you can divide the different ways in which you structure your code into four paradigm. That is Procedural, Functional, Logical and Object Oriented. There also others (e.g. Aspect Oriented) but I will ignore them for today.
The procedural way is approximately the thing you would do in C (assuming you are not using your own OO emulation with structs or so) where you have functions, variables and calls. In OO you have objects, methods and messages but everybody does its own things anyway.
And then there is the functional way. Unlike programs from other paradigm in which you change state and data all the time to achieve your result, functional programs do not hold changeable state nor use mutable data (ignoring I/O for now). This is maybe the most obvious difference.
Maybe the exception before occurred because you forgot to call init() and used matchesRegex(…) directly. Or concurrent calls on getFac() resulted in race conditions. Or you were iterating over a collection while it got modified. Or you “cached” a state from an object because you thought it will be too costly to call every time but in the end failed to update it properly.
All those problems occurred because a common resource was accessed incorrectly. As soon as you start using those shared resources (that does not have to be the all-time-evil singleton, also class attributes may bring you into troubles) you need think about how you initialize them and in which order. Which values may be null? Where do I verify all my data? What happens on concurrent calls, do they mess everything up? What will happen when I throw an exception, do I reinitialize properly?
One of the main points in functional programming is that you avoid having shared resources as much as possible. The matchesRegex(…) does not have any mutable attributes in it’s class and initializes everything at its own. The getFac() does not get calculate the factorial out of a value passed in the class’ constructor, it accepts that value as parameter. All needed data is passed directly from the caller to the method, you don’t have any locking problems anymore because nothing is shared.
Furthermore, because of its stateless design, passing the same parameter to a function will also always return the same result.
It does not depend on that other method DoEvil() which sets the class attribute google you use to a state you never thought of before, it’s more like math: The Square root of four will return two also when you calculated exp(4) thousand times before. Those functions do not share data between each other thus wont affect each other. Because everything runs at it’s own, the compiler has also the possibility to optimize and split your program over several threads and CPUs automatically. Of course, no shared data means no need for synchronization mechanism which will let the program run truly faster because no synchronization information have to be passed between the CPUs.
“But we have to do it in Java” I hear you whining (I bet some of them are actually happy about it so they can continue using their lame editor… giusi?)
Java isn’t a pure functional language at all, but that functional stuff is just a programming paradigm and thus not bound to a language. Because Java is a multi paradigm language and tries to be THE language for everything (somehow explains why it’s so crappy) you can also implement your programs in a more or less functional way. Of course it’s not as easy as it would be if you’d use a special purpose language nor will you get the benefits of an fp environment neither. But if used correctly, you eliminate the whole category of those side effect errors.
In most languages you can program in a functional style. While it won’t look as beautiful and won’t achieve the same parallelization as for example in Haskell it does protect you from an annoying type of bugs.
Write functional, also if you use a lame language!
