Java from a functional perspective

Not long ago a project required me to learn a little Java. As a long-time elitist functional programmer, I was not extremely excited. Due to the low quality of Java software I have used, I assumed, like many, that Java produced slow, bloated, and buggy software. Some languages just feel clunky.

My previous experience with Java was as a less experienced programmer and I had some difficulty with the type system. I learned on dynamically typed languages. My first experience with static typing was in modern functional languages, where type was inferred automatically by the compiler. Explicit type declarations felt archaic and overly wordy.

My experience this time around, however, was more positive. This is primarily due to three factors.

NetBeans

NetBeans is Sun’s Java IDE. Because it is mostly limited to Java, its syntax formating is excellent. It takes a lot of code to abstract the ability of an IDE to format multiple languages (in particular, the ability to format both C-style languages and Lisp-style languages using the same application primitives presents difficulty). NetBeans has the Apple advantage in this; one language to support means that it can have excellent support for that language. Of course, this means that projects that use multiple languages are more difficult to develop using NetBeans, so perhaps this tradeoff is not worth it.

Java’s self-documentation is very nice, too. NetBean’s code-hinting is superior to most, although it can get in the way.

The GUI builder is also extremely nice. Swig and AWT can be a real trial in a language as wordy as Java (although I think Sun prefers us to call it “explicit.”)

Classes

I initially had some difficulty writing entire programs in objects. Most languages I use that are object oriented are multi-paradigm. Classes are available, but then utilized within functional or procedural code. Because of this, I tend to regard classes as a sort of extra-powerful type struct, only to be used when a type becomes complex enough that the extra work of encapsulated it within a class becomes advantageous.

It’s (unfortunately) common to see new Lisp programmers try to simulate OO in Lisp using closures and hashes (especially if they’ve read a few Paul Graham essays). I don’t particularly see that OO improves Lisp; closures and templates provide roughly the same functionality. Exactly replicating closures in OOP or objects in functional programming would be moot. They are different styles; Java-style programming is as uncomfortable in Lisp as Lisp-style programming is in Java.

While writing my initial applications, though, I realized something: classes are a formalized closure syntax. They are a function that builds functions and closes over their variables.

This freed me to use a style of abstraction in Java that felt much more comfortable to me without the drawback of attempting to use the wrong paradigm for the language. I could now program using classes and objects in a manner consistent with how I mentally model my applications.

Something I missed quite a bit was pattern matching. It is very helpful to declare local variables based on the pattern of the argument(s) passed to a function, but that would not be useful in Java, since the primary type mechanism in Java is the class rather than the list. Method overloading provides much of the same functionality, but idiomatic of Java.

Write once, run everywhere

Lisp pioneered the virtual machine. Lisp is compiled into code that is run within the Lisp interpreter. But Lisp is not commonly installed on computers, so distribution of Lisp software becomes a real challenge. One of the advantages of having a huge amount of money behind a language is that Java is installed on virtually every computer a program may end up on.

It’s common in Lisp to have to code various parts of the program differently depending on the operating system and Lisp distribution. For example, very few Lisps support multi-threading on OSX. It makes it agonizing to write threaded software for a multi-platform application.

Java does not have this problem. A feature is available on all platforms or none at all. While this means that the language sometimes suffers from the lack of a particular feature, it also means that there is a guarantee against discovering too late that a feature used in the core of your program will not limit its utility on other operating systems.

Conclusion

Java is better than I had given it credit for. With NetBeans taking care of checking your work for you, I am beginning to suspect that the many buggy Java programs are due to poor programming rather than a problem inherent in Java itself.

I still have some doubts as to how useful it would be for a very large project; my experience has been that object orientation and inheritance results in unnecessary complexity.

For small projects and GUI applications, though, Java seems to be a fair choice.

Leave a comment | Trackback
Oct 15th, 2007 | Posted in Soap box
Tags: , ,
No comments yet.