So what actually is my favourite programming language?

The recent series of Why XYZ Is Not My Favourite Programming Language articles has been fun to do, and it’s been great to see the discussion in the comments (even if it’s mostly people people saying that I am talking a load of fetid dingo’s kidneys). But I don’t want to extend that series beyond the point of diminishing returns, and it’s time to think about what it all means. As duwanis commented on the Ruby article, “I’m a bit lost as to the point of these posts”; now I want to try to figure out just what, if anything, I was getting at.

By the way, it’s been interesting how people respond to articles that are critical (however flippantly) of languages. Most of what I’ve written here on TRP has had comments pretty evenly balanced between “Yes, I know exactly what you mean” and “You are talking complete nonsense”, which seems about right to me; but comments on the NMFPL posts have almost all been telling me why I am wrong. It’s also been interesting to watch all the Reddit posts for these articles drop to zero, or at best stay at one: evidently people who like languages are keener to defend them than those who dislike them are to pile in — which is as it should be.

Reviewing the languages

First of all, let me say that all the languages I picked on are, or at least have been, good languages. I didn’t bother criticising BASIC or FORTRAN, or Tcl for that matter, because, well, everyone already knows they’re not going to save the world. (I didn’t criticise any of the functional languages because I don’t honestly feel that I yet know any of them well enough to do an honest job of it.)

So, to look at the positive, here are some reasons to like each of the languages I’ve been saying are not my favourites. In roughly chronological order:

C (1972) was, depending on your perspective, either the first really expressive low-level language, or the first really efficient high-level language. Its historical importance, as the foundation of all but the earliest implementations of Unix, is immense. But, more than that, it has a crystalline elegance that few other languages approach. (I’ll be writing more about C in future articles.)

C++ (1983), despite being more prone to abuse than any other language, can indeed be used as Stroustrup suggests, as “a better C”. It was also a very impressive technical achievement: to come so close to being object oriented while retaining binary compatibility with C is pretty astonishing. It solves that problem well, while leaving open the question of whether it was the right problem to solve.

Perl (1987) was and is amazingly useful for just, you know, getting stuff done. It has a likeable humility, in that it was the first major language to make working together nicely with other languages a major goal, and its Swiss Army Chainsaw of text-processing methods were a huge and important pragmatic step forward. It’s not pretty, but it’s very effective.

Java (1995) can be thought of as “a better C++”; and it is better in lots of important ways. It hugely reduces the amount of saying-it-twice that C++ source and header files require, the code is much cleaner, it is much harder to shoot yourself in the foot, and experience tells us that it scales well to very large projects with many programmers.

JavaScript (1995) has proven its usefulness over and over again, despite being saddled with a hideous set of largely incompatible operating environments; and underneath that perplexing surface, as Douglas Crockford’s book The Good Parts explains, there is a beautiful little language struggling to get out.

Ruby (1995) is in a sense not really a huge leap forward over previous languages; but it’s done the best job of any of them in terms of learning from what’s gone before. It really does seem to combine the best parts of Perl (string handling, friendliness towards other languages), Smalltalk (coherent and consistent object model), Lisp (functional programming support) and more.

Although there are plenty of other languages out there, these are the main contenders for the not-very-coveted position of My Favourite Programming Language: I am deliberately overlooking all the Lisps and other functional languages for now, as I just don’t know them well enough, and I am ignoring C# as a separate language because even highly trained scientists with sensitive instruments can’t tell it apart from Java; and PHP because it’s just Even Uglier Perl, and Visual BASIC for all the obvious reasons. (I don’t really have a good reason for leaving Python out, but I’m going to anyway.)

Some thoughts on Java

According to the Normalized Comparison chart on langpop.com, and also the same site’s Normalized Discussion Site results (at the bottom of the same page), Java is currently the most popular programming language of them all (followed by C, C++, PHP, JavaScript and Python), so in a sense it’s the reigning champion: if you want to be an advocate for some other language, you need to make a case for why it’s preferable to Java.

And it’s a good language. At the cost of some expressiveness, it tries to make itself foolproof, and it does a good job of it. In a comment on the recent frivolous Java article, Osvaldo Pinali Doederlein boldly asserted that “there are no major blunders in the Java language”. Surprisingly enough, I do more or less agree with that (though its handling of static methods is pretty hideous). I think that almost-no-major-blunders property is a nice consequence of Java’s lack of ambition: it was pretty much deliberately designed as C++ Without The Compromises To Keep It Binary Compatible With C, and it did a good job of learning from C’s and C++’s mistakes, to produce a language that is much smaller and more pleasant than C++ and perhaps on a par with C for both size and pleasantness while being much more convenient.

My main issue with Java is actually much more pervasive than any specific flaw: you’ll forgive me if I find this hard to tie down, but it’s just a sense that the language is, well, lumpen. Everything feels like it’s harder work that it ought to be: programming in Java feels like typing in rubber gloves.

An obvious example of this is what Hello World looks like in Java:

public class HelloWorld {

public static void main(String args[]) {

System.out.println(“Hello, world!”);

}

}

You have to say a lot of stuff before you can say what you want to say. You have to have a main() function, it has to be declared as taking an array of String and it has to be public static void. It has to be wrapped in public class SomeIrrelevantName (which, by the way, has to be the same as the name of the source file.) The print() function is called System.out.println(). The comparison with complete Hello World programs in other popular languages is instructive:

print “Hello, world!\n” # Perl

print “Hello, world!” # Python

puts “Hello, world!” # Ruby

(print “Hello, world!”) ; Emacs Lisp

10 PRINT “Hello, world” :REM Commodore 64 BASIC

Is it a big deal that Java makes you say public static void main(String args[])? No, it’s not. It’s easily learned, and Java programmers develop the ability to become “blind” to all the syntactic noise (at least I assume good ones do). But it’s pervasive. All Java code looks like this, to a greater or lesser extent. How many mental CPU cycles do Java programmers burn filtering out all the keyword soup?

At the risk of looking like a total Steve Yegge fanboy, I’ll illustrate that with an example taken from his article on Allocation Styles: how to ask a language what index-related methods its string class supports (i.e. which methods’ names contain the word “index”). His Java code looks like this:

List results = new ArrayList();

Method[] methods = String.class.getMethods();

for (int i = 0; i < methods.length; i++) {

Method m = methods[i];

if (m.getName().toLowerCase().indexOf(“index”) != -1) {

results.add(m.getName());

}

}

String[] names = (String[]) results.toArray();

Arrays.sort(names);

return names;

If you’re a Java jockey by nature, you’re probably looking at that and thinking “well, that doesn’t look too bad” (though quite possibly also thinking about a couple of incremental improvements you would make).

Here’s how that program looks in a less verbose language (Ruby, as it happens):

“”.methods.sort.grep /index/i

Now even if you agree with me and Osvaldo that “there are no major blunders in the Java language”, you have to admire the concision of the Ruby version. It’s literally an order of magnitude shorter (30 characters vs. 332, or one line vs. 11).

What a concise language buys you

“But Mike, surely you’re not saying that the Ruby version is better just because it’s shorter?”

Well, maybe I am. Let’s see what the advantages are:

Less code is quicker to write than more code.

Less code is easier to maintain than more code. As Gordon Bell has pithily observed, “The cheapest, fastest and most reliable components of a computer system are those that aren’t there.” Each line of code is a line that can go wrong.

Concise code lets you see more of the program at once: this isn’t as big a deal now we all have 1920×1200 screens rather than the 80×24 character terminals that I did all my early C programming on, but it’s still an important factor, especially as programs grow and start sprouting all kinds of extra glue classes and interfaces and what have you.

A concise language keeps the total code-base size down. I think this is very important. ScottKit currently weighs in at 1870 lines of Ruby, including blank lines and comments (or 1484 once those are stripped). Would I have started a fun little project like that at all if it was going to be a fun big project of 20,000 lines? Probably not. And this factor becomes more important for more substantial projects — the difference between ten million lines of code and one million is much more significant than the difference between ten thousand and one thousand.

Most importantly, look at what code isn’t in the Ruby version: it’s all scaffolding. It’s nothing to do with the problem I am trying to solve. In the Java version, I have to spend a lot of time talking about ArrayLists and Italian guys and loops up to methods.length and temporary String[] buffers and Italian guys. In the Ruby version, it’s a relief not to have to bother to mention such things — they are not part of my solution. (Arguably, they are part of the problem.)

I think the last of these may be the most important factor of all here. I’m reminded of Larry Wall’s observation that “The computer should be doing the hard work. That’s what it’s paid to do, after all”. When I stop and think about this, I feel slightly outraged that in this day and age the computer expects me to waste my time allocating buffers and looping up to maxima and suchlike. That is dumb work. It doesn’t take a programmer to do it right; the computer is smart enough. Let it do that job.

The upshot is that in the Ruby version, all I have to write about is the actual problem I am trying to solve. You can literally break the program down token by token and see how each one advances the solution:

“”.methods.sort.grep /index/i

Here we go:

“” — a string. (The empty string, as it happens, but any other string would do just as well.) (I notice that WordPress inconveniently transforms these into “smart quotes”, so that you can’t copy and paste the code and expect it to Just Work. D’oh! Use normal double quotes.)

.methods — invoke the methods method on the string, to return a list of the methods that it supports. (You can do this to anything in Ruby, because Everything Is An Object.)

.sort — sort the list alphabetically.

.grep — filter the list, retaining only those members that match a specified condition.

/index/ — the condition is a regular expression that matches all strings containing the substring “index”.

i — the regular expression matches case-insensitively.

Bonus pleasant property

As a bonus, the code reads naturally left-to-right, rather than inside-to-outside as it would in a language where it all has so be done in function calls, like this:

grep(sort(methods(“”)), /index/i)

I think that Ruby’s object-oriented formulation is objectively better than the pure-functional version, because you don’t have to skip back and forth through the expression to see what order things are done in.

“Say what you mean, simply and directly.”

When I started to write this article, I didn’t know what my conclusion was going to be. I just felt that I ought to say something substantial at the conclusion of a sequence of light-and-fluffy pieces. But, as Paul Graham says [long, but well worth reading], part of the purpose of writing an essay is to find out what your conclusion is. More concisely, E. M. Forster asked, “How do I know what I think until I see what I say?”

But now I’ve conveniently landed on an actual conclusion. And here it is. Remember in that Elements of Programming Style review, I drew special attention to the first rule in the first proper chapter — “Say what you mean, simply and directly”? The more that runs through my mind, the more convinced I am that this deceptively simple-sounding aphorism is the heart of good programming. Seven short words; a whole world of wisdom.

And how can I say what I mean simply and directly if I’m spending all my time allocating temporary arrays and typing public static void main? My code can’t be simple if the functions I’m calling have complex interfaces. My code can’t be direct if it has to faff around making places to put intermediate results. If I am going to abide by the Prime Directive, I need a language that does all the fiddly stuff for me.

So it looks like My Favourite Programming Language is Ruby, at least for now. That might change as my early infatuation wears off (I’ve still only been using it for a couple of months), and it might also change as my long-anticipated getting-to-grips-with-Lisp project gathers momentum. But for now, Ruby is the winner. And it’s going to be dethroned, it’s not going to be by a scaffolding-rich language like Java.

Coda: I don’t hate Java

Just to defuse one possible stream of unproductive comments: this is not about me hating Java. I don’t hate it: I think it’s way better than C++, and in most ways better than C (which, given that I love C, is saying a lot). All the criticism I’ve levelled at Java in this article applies equally to C++, C and C#, and many other languages. To some lesser degree, they also apply to Perl and JavaScript.

But I am on a quest now — to say what I mean, simply and directly. And Java is not a language that helps me do that.

.

Update (19 March 2010)

The discussion at Reddit is not extensive, but it’s well worth a look because it contains some nice code samples of how you can do “”.methods.sort.grep /index/i in other languages.

This is a fine example why hackers of the world don’t take pleasure in Java programming.

I don’t hate Java either, it’s got qualities, but I would hate to do anything in it.

And I really like Ruby too. It has another set of qualities, especially the consistency (Matz’s principle of least surprise, I just don’t get that feeling from Python at all, indenting issues aside). I am not surprised that it appeals to many smart people.

Language doesn’t have to be easy as Ruby to be pleasurable, I don’t really mind C at all and I used assembler too. When you know your way around programming languages you just feel there is something wrong (like Java or C++). “Great minds” think alike? :)

And I also think that 80 characters wide text buffer should be enough. ;)

While I wouldn’t deny that Ruby is more succinct than Java, in this instance Steve Yegge’s code stinks. He either doesn’t really know Java, or he’s being deliberately mischievous to make his point.

Here’s a much cleaner and more concise version that will return the “index” methods of any class.
It took me less than a minute to write. It has the added advantage of not containing any bugs – unlike Steve’s version.

I think you may be conflating several things here. I used to love APL for writing concise programs. Everything was done with arrays, array operators, expand and reduce. That let me write extremely concise, but often unreadable code. For example, looking up a string in a table would be something like:

(TABLE^.=STRING)i1

That’s a matrix multiplication using a boolean and and an equals operator to produce a boolean vector of where the STRING appeared in the TABLE, the former being a vector and the latter a matrix. The i was the iota operator for finding the index of the first value in the result vector.

It was beautiful, but every line was a puzzle.

You seem to have two complaints about Java.

One is that Java is largely scalar, without a lot of clever vector, map and reduce, or pattern match and replace operators. That’s a valid complaint about the language density. COBOL and Applescript are notorious for their low expressive density because they try to look like a natural language. You can destroy your brain at either extreme.

The other complaint is that Java requires code to be placed in context. A lot of the text of a program does not advance the algorithm directly, but focuses on what the code does within the overall program. The code is descriptive, not prescriptive. Itdoesn’t run. from the top of the page to the bottom as in a straight forward narrative, but lives in various compartments and those compartments interact with each other. You can actually read the code or the context, much as we can parse DNA with introns, regulatory sequences and coding sequences.

When you just want to write a quick hack to fix something, it is nice to have a language which strips out the contextual overhead and just does something. Of course, if your program proves useful, you are likely to wind up gluing it to a host of other similar hacks using the shell or some other patchwork. If I recall, dealing with this patchwork of program components was noted rather negatively at one point.

a) You can make your Ruby example more expressive by turning it into:
String.instance_methods.sort.grep /index/i
Which leaves out the need for the arbitrary string by explicitly stating “All methods applicable to instances of String.” It’s not as short, but that’s not always what expressive is about, eh? :)

b) In fairness to Java, that’s an outdated bit of code you’ve quoted, and it doesn’t take advantage of some of Java’s newer niceties (like the For-each loop, for example). It can also make use of String.matches(regex) rather than doing the clumsy .toLowerCase().indexOf(“index”) != −1 business.
Not that those really help a lot, but they do make it much easier to read.

c) As someone who was a Java developer for many years, you *do* learn to filter out all the keyword cruft… until you start learning other languages. Once you start learning Python and Ruby, for example, writing Java becomes more and more painful.

There are worse things in life than being a Steve Yegge fan(boy). His drunken blog rants are mostly on target.

My co-workers just “love” Java. I like it too. I can whip things up really quickly in it but all the line noise really gets to me these days.

Why do I have to deal with so much boilerplate?

Do I really have to create (yet) another interface for this damned object?

Yes. I know. Its the way the language is and there is no point in complaining about it.

Except there is a point.

When all you have is a hammer, everything looks like a nail.

After all these years using Java I am coming to the conclusion that it is merely a different kind of hammer to the others I have used before — C and C++.

What I need is a new tool — a screwdriver.

I have tried to like Python. I was really nice about it during that interview with The Google a few years back but, seriously, isn’t __self__ some kind of joke? Having said that I really like the whole indention thing but I’m a bit of a weirdo that way.

These days I find myself looking at Clojure, Ruby, Scala and (believe it or not) Go. If Ruby performance wasn’t such a dog I’d be off down that road at 1000mph. Still, performance will get better and not just because CPUs get more powerful.

Heh… I “get” to work with classic ASP/VBScript daily, and it offends on all fronts here. Inability to declare and initialize on the same line? Check. Reading inside-out? Check. Lack of a concatenation-assignment operator? Check check check. It’s like the language wants me to write solutions that are inefficient and unmaintainable.

I do. I hate Java with a fucking passion. It’s crappy APIs punish me everytime I’m forced (for I would never do so willingly) to write java. Fuck those assholes at Sun. They easily could have done a better job. No wonder they had to have a system like javadoc, because you’ll spend half your development time searching for method sigs.

I wonder how much will tooling help you writing that one line of code or maybe even explaining it later on during code review?

In Java and using a modern IDE I can actually click on most of the code parts (classes, method invocations and such) in that file.

So if you would explaining the code to me and you said that methods invocations returns all methods and I would ask you if you’re sure that public and private ones both are returned? How can you show it to me? Would you need to google documentation or is there an easier way?

Or if want to check the type that is returned from methods and check all methods that the object has, what would be my steps?

I tend to program mostly in Java, but use python and PHP for some other projects and main distinction I’ve seen is that you have this excellent tooling compared to just vimming in the other languages.

toomasr, my take on that is that Java’s huge IDEs are there to help work around the deficiencies of the language — to help you not have to think so hard about all the boilerplate. But the easiest boilerplate of all to think about is the boilerplate that just isn’t there.

Big IDEs worry me for another reason: it seems that in some programming cultures (and again, I don’t JUST mean Java, but it does examplify this trend), the response to any technical deficiency is just to build yet more technology on top — which leaves you with yet more stuff to learn. I’d much rather take more time to get the foundation of my building right than build an edifice of scaffolding to hold it up, only to find that I then need to maintain the scaffolding as well.

@futilelaneswapper has beat me with the better Java code. I would add that the Ruby code also reveals an imperfect language – for one thing it’s horrible that any object responds directly to a “methods” message; “”.class.methods.sort.grep /index/i would be concise enough (with an extra “class” call). It seems that Ruby’s root Object type is a bit polluted. This is probably due to the heavy use of MOP in the language, but that’s still a tradeoff, not and example of a heaven-perfect design. Even Smalltalk, that didn’t care about the number of public methods in the root classes, required to send first a “class” message to later grab the methods etc.

Also, in Java, adding utility methods like sort() to array/collection classes would also be a problem because then you enormously expand the size of important interfaces like Collection and List, so every new implementation of those is required to implement much more methods (including many methods that will be just delegates to some common implementation). So this reveals a classic tradeoff of static-typing versus dynamic-typing. Ruby classes can have two hundred methods without much harm because you rely on duck typing, you can provide alternate implementations that don’t necessary inherit the existing classes, and don’t necessary implement all their methods. But I will stick with the advantages of static-typed languages, even with the extra verbosity. Other “issues” of Java verbosity, like longer method and variable declarations, also come off static typing and exist in most other static-typed languages, so I’d say that Java’s major defect is not having a modern typesystem with Hindler-Milner inference or similar (for this look at Scala, or even JavaFX Script).

Finally… @futilelaneswapper would be a bit shorter if the method is not required to return a primitive array, just return a collection! And will be even shorter in Java7 with lambdas (this is another item that is also sorely missing in Java, but we’re fixing that, finally).

Hi, Vince! (That’s “futilelaneswapper”, for those of you who don’t know him.)

I suspect Steve Yegge was neither ignorant not mischievous — probably just using an earlier version of Java. Anyway, your version certainly looks like an improvement. I wrapped it in a public-static-void-main function and a class, and added what seem to be the necessary imports, in the hope of seeing it work. I got:

Osvaldo: yes, it does seem that a lot of the scaffolding that I’m finding such a drag(*) is related to static typing. I’d like to do an article about the pros and cons of static-vs.-dynamic, but for this particular topic Steve Yegge has covered the ground so thoroughly that I’d have almost nothing new to say. (Sorry, yes, more fanboyage.) If you’re interested in an open-minded and balanced view, I recommend his article Is Weak Typing Strong Enough? at http://steve.yegge.googlepages.com/is-weak-typing-strong-enough

I do see both sides of this equation. But I think it’s pretty clear now what side of the fence I’ve fallen on, so I won’t pretend to neutrality :-)

(*) I didn’t want to use the phrase that I am “finding it such a drag” because it’s such a lazy colloquialism, but in this case it’s actually a perfect description of the situation. Drag is exactly what the scaffolding is imposing on me, like trying to move through a viscous medium.

Ah, the enthusiasm of the first days of Ruby adoption. Been there, done that. Came back to Java crying.

I totally agree with toomasr – Ruby IDE support just plain sucks for now, and i just don’t how can it be drastically improved in the future. This is just what you get from such a language.

And speaking of the real world – the myth that Ruby is easier to maintain is just plain false. Ruby is far more prone to the situation when you’re looking at your own code (that was written a while back) and say – what the hell does this do?

toomasr, sorry to reply twice to your comment, but I only just registered this bit:

If you would explaining the code to me and you said that methods invocations returns all methods and I would ask you if you’re sure that public and private ones both are returned? How can you show it to me? Would you need to google documentation or is there an easier way?

Yes, there is a much easier way — just ask the language itself! First ask it what it can tell us about methods, then use one or more of the methods it provides to ask the specific question you’re interested in:

@Nike: I have read Steve’s static/dynamic rant now. Most of his Cons of Static Typing are, IMHO, in the range of highly debatable, to sheer stupid and false statements.

It’s worth notice that some of these items can backfire in the debate against dynamic typing. For one thing, take Steve’s points 4 (false sense of security) and 5 (sloppy documentation). [These are in the stupid/false category.] Yeah I suppose that some bozos think that they don’t need to write any test because the language is static-typed so the compiler catches so many errors; and no documentation either because the code is more explicit, IDE can do perfect browsing and refactoring etc. But we should not judge a language from the habits of incompetent users. I program in Java and my code is well documented and tested. It’s a matter of discipline. Now, let me flip the coin and look at dynamic languages: they tend to NEED extra effort in both testing and documentation, to compensate for the missing guarantees and explicit info that static typing would provide. So, we could look at the tests and docs that a (professional, mission-critical, well-maintained) Ruby app contains in excess when compared to a similar Java app, and categorize these as “scaffolding”. Now the Ruby hacker will be typically pose as a superior developer because his version of the code contains 2,500 unit tests while my version contains only 700 tests – for Agilists/TDD’ers it seems that humongous test suites are obvious evidence of excellence – but the hard fact may be that my version, with much less tests, is more reliable and simply doesn’t need as many tests. (Tests are also code that has a maintenance/evolution cost, you know.) The same arguments are valid for documentation, with the big extra problem that broken docs won’t be caught even by a good test suite. (So, the only really good code is code that’s clear enough to not require detailed documentation.)

Now let me finish this with a real story. A few days ago I’ve got a quick freelance job to fix two bugs and add some simple enhancements to an old Java program, which does some interesting particle-based 3D visualization – runs with good performance even on old and unpowered J2ME devices without any 3D acceleration (take that, Ruby!). The code is well-written, but it contains zero tests; all documentation including code comments is written in German (which I don’t grok beyond ja/nein); the original author is not available to help and the guy who hired me is not a developer so I was basically on my own. But no problem: the code is crystal-clear, I fixed the offending bugs in the first hour of work, and added the new features in the first (and single) day of work, job finished – in a code base that I’ve never seen before. In fact, so far I didn’t bother to read >95% of the code. Testing effort was ridiculously minimal. This is the wonderful world of a language like Java. ;-)

Osvaldo, I don’t understand why you’d characterise such a balanced, exporatory article as a “rant”. It begins with “I’d love to know the answer to this” and ends with “This is a hard problem” — not really what I’d consider the hallmarks of rantitude. I also don’t find it at all obvious that Yegge’s static typing cons are “sheer stupid and false”, any more than his static typing pros are.

I can’t help wondering whether you’ve just made up your mind in advance what your conclusion is going to be.

No arguments about these two statements of yours, though: “Tests are also code that has a maintenance/evolution cost”, and “the only really good code is code that’s clear enough to not require detailed documentation.”. It’s nice that we get to agree on something!

Mike: Ok, that might have been a bit hard on Steve’s article. The fact is that even with his soft language, I disagree vehemently from some of his findings. And yes, I am a static-typing bigot, like I often confess in these discussions. So you are probably right to say that I’ve made my mind before reading Steve’s blog; but I didn’t made my mind in five minutes – I’ve been making it since I was 13 years old with my ZX Spectrum, and I’ve fallen in love with both camps – e.g. Eiffel as the early champion of static typing (Meyer’s OOSC is still the SINGLE programming book that’s 1300 pages and worth reading cover-to-cover), and Smalltalk as an early and über-dynamic language.

Having said that, other people may be ten times as smart and experienced as I am and still have opposite conclusions, and I respect that – but then, Steve’s used some old and tired “cons of static typing” (although the facts-list is followed by a discussion of much better quality); and on top of that, Steve makes a classic confusion of terminology, mixing together the concepts of static/strong typing, and weak/dynamic typing. He is a brilliant hacker and he did have formal CS education, so maybe programming language design is just not his focus, or he is just in the camp that doesn’t care much about formal language/compiler theory. So call me an academic elitist – in fact it’s been many years that I don’t read a single programming book, only research papers — but when it comes to programming language I clearly expect a lot of people who have something to say.

It is odd that, having consistently said strong/weak typing throughout when he meant static/dynamic typing, he then went to all the trouble to “explain” at the end that the mistake was deliberate, rather than just fixing it.

I like the fact that Lisps (like Clojure) allow me to say something like (-> “” methods sort (grep /index/i)) if I want to, instead of (grep (sort (methods “”)) /index/i) being my only option. The fact that this sort of syntax creation is possible gives it the edge (in my mind) over languages that enforce one way of thinking over all of the others that I might want to use.

Looking over the documentation for Object doesn’t suggest any ‘pollution’ – sure, it has more methods than the Java object, but Ruby handles more of its functionality in methods than Java does (operators, etc.).

Mike: When you call System.out.println on an object, Java invokes the toString() method of that object and prints whatever it returns. So what you are seeing is the output from Array.toString(): an object Signature, followed by its memory address in hex. This is the default behaviour for all objects that don’t override toString() themselves (like Array). Sp you need to traverse the array yourself and print each String object in turn:

for (String s : myArray) {
System.out.println(s);
}

There are good reasons for this behaviour, but it is admittedly a bit of a pain. However, as Oswaldo has pointed out, there’s a bunch of unnecessary conversions going on in Steve’s code, which for the sake of fairness I have maintained in my version of the code. The most obvious issue is that having iterated over one collection to create a result set, we then iterate over the result set to get what we really wanted in the first place! Ugh.

Incidentally, the bug in Steve’s code, in case you hadn’t figured it out, was his use of a List to hold method names. The String class overloads its two index methods, so the List ends up holding multiple copies of the same method name.

As for the unsafe conversions, the correctly typed version was mangled when I posted it by WordPress. It removed everything in angle brackets.

I liked your series of posts on why these weren’t your favorite languages. All languages have their (mis)features, and it fomented a lot of interesting discussion.

I also have to say I agree completely with your summary of C++. It is by far the most concise and precise description I’ve seen. I think I’ll make up a poster of it at some point and hang it over my desk, if you don’t mind.

I’ve followed Java developments over the years, but I was never inspired to jump on that particular bandwagon. It didn’t seem to solve any of the problems I needed solved in a better fashion than C/C++ and added a whole new layer of dependency in the VM. The fact it gained such a following in the server/enterprise space took my by surprise. Although, in hindsight I understand why that happened.

I now regret not gaining some experience with Java development as it seems a great many jobs require decades worth of Java experience to even be considered. Alas! My misspent youth!

Thanks, Charles, for generously overestimating the value of my C++ summary :-) I recently read a much better, or at least much snarkier, summary: “an octopus made by nailing extra legs to a dog” (Steve Taylor). Harsh, but perhaps not entirely unfair.

Vince: but why on earth would Array.toString() not return something useful? Something like a newline-separated list of the members’ toString() results would do, or comma-separated, or something. Just not “[Ljava.lang.String;@c17164”, which reads like a run-time buffer overflow.

Anyway, I tried to do what you suggested in the context of the little program that had built the collection called methods:

for (String s : methods) {
System.out.println(s);
}

But that wouldn’t compile: “incompatible types”. So I tried converting methods to an Array, and using for (String s : methods.toArray()), but that was rejected too. I tried a couple more incantations, then thought — hang on, what the heck am I doing? This is exactly what I am trying to get away from. Guessing vocabulary is all very well when you’re playing 1980s Adventure games (GIVE HONEY doesn’t work, you have to type OFFER HONEY), but it’s no way to write programs. Surely the whole point of the so-called smart for-loop is that it works on all collections? So why doesn’t it?

Not to keep beating the same dead horse, but in Ruby you would say collection.each { |member| do_something(member) } and it Just Works, every time, whatever kind of collection collection. Is there a compelling reason why Java can’t do the same?

To pretty-print an array in Java, you should use java.util.Arrays.toString(array). That will take in an array of any type (it’s an overloaded method) and return a String. Is this defective behaviour? Yeah. Sun should have changed the definition of toString() for arrays directly (what you are seeing is the internal representation of the array’s _type_). But Sun decided to leave the warts in Java, build new stuff instead, and hope that documentation will cure all ills.

However, it’s all silly in this context, because you don’t need to convert a Set to an array to print it out. If you want to print it out, simply using:

it seems like I’m the first one to point this out, but your example on how to find names of all method names containing indexes is incorrect. Take a moment to run it (http://snipt.org/GpG) to verify that.

The problem is that an Object[] cannot be cast to a String[] even if it contains only strings. Fun but true …

The group I work for conducts very extensive code reviews. One of the things we strive for is to make the code as succinct as possible without being obscure. We feel strongly that succinctness makes the code easier to learn an maintain. So, I agree with your argument about the importance of conciseness. However, 90% of our code is Java, so I always feel as if we are fighting a losing battle in striving for conciseness.

I find it interesting that I can’t get anybody in my group to consider changing languages, yet at the same time I feel that with Java, we are trying to prevent the tide from coming in. I guess the devil you know…

I think you should take another look at C#. I only spend about 5% of my time coding in C#; I’m definitely not very experienced with the language. However, C# is evolving very much faster than Java. The new .NET 4.0 version is close in features to Scala. In general, I don’t like being tied to a particular platform, but C# is becoming very interesting.

The Java world has seen the emergence of languages much more interesting than Java itself: Scala, Clojure, and Groovy.

Groovy, as the phonological similarity indicates, was conceived as a Ruby-like language for Java. The index filter is a similar one-liner:

String.methods.name.sort().findAll{ it =~ /(?i)index/ }

I spent a couple of years programming in Groovy and just loved it.

But these days I find the most fascinating language around to be Clojure. It’s a Lisp dialect for the JVM, more purely functional than traditional Lisps, with a
strong story about how to handle concurrency and state. Rich Hickey, the author of the language, has made some wise choices about what Lisp baggage to leave behind, recognizing, for instance, that there’s more to data structures than linked lists. It’s a compelling piece of language design. If you’re really looking to get into the world of functional languages, this is a great place to start.

The JavaScript veersion is pretty nice (though it seems weird that the methods for listing String methods is a method of Object rather than of String). What does the .test at the end mean?

I feel bad about JavaScript. It seems like it’s that close to being a good language, but falls short for a variety of reason, not all of them the language’s fault (e.g. the horribly incompatible DOM implementations in the various browsers). But some of the failings — the the single global namespace — are its own fault.

1. Maybe “String.keys()” works, not sure
2. .test is a method of any RegExp object as in /index/i.test(“myindexstring”) (which returns True); /index/i.test is a function/method (passed to filter) which will be applied to every array element from the array returned by sort()
3. Forget all about JS+browser+DOM and checkout serverside Javascript at http://commonjs.org/ and/or http://nodejs.org/

A good sign of languages that are ‘part of the problem’, as you suggest, is the existence of ‘design patterns’ and books of ‘design patterns’ for these languages. Think what those are; they’re instructions to the human about how to model some repeatedly-needed construct so that the computer can understand it. If the language were sufficiently expressive, you could express this *in the language* and never need the books in the first place. (All these books say that you cannot express patterns in computer languages. They are wrong.)

(This is not an original insight and you have doubtless encountered it before in the writings of Paul Graham. But I thought it was worth reiterating here. You do need a decent macro system to do this, but these *are* implementable in non-Lispy languages, e.g. Metalua.)

btw, another wonderful description of C++, from a years-old post on alt.sysadmin.recovery:

“No, no. C is a small sharp knife. You can cut down trees with it, and get it cut down exactly the way you want it, with each shaving shaped exactly as you wish.

C++ is a small sharp knife with a bolted-on chainsaw and bearing-mounted laser cannon rotating at one revolution per second wildly firing every which way. You can cut down trees with it, and get it cut down exactly the way you want it, with each shaving shaped exactly as you wish.

You can also fire up the chainsaw and cut down the entire forest at one go, with all the trees cut down exactly the way you want them and every shaving shaped exactly as you wish — provided that you make sure to point the wildly rotating and firing lasercannon in the right direction all the time.”

@Nix: You are a bit off with design patterns. First, the books don’t say that you can’t express patterns in programming languages – this wouldn’t make sense. I think you mean that you can’t express the pattern as a single, reusable implementation, so you can have library-provided patterns that you just call from app code, or “plug” into app code through some mechanism (inheritance, composition, templates, aspects, whatever).

My MSc thesis was focused on the automatic detection of design patterns in existing code, I have researched the field pretty well [back in 1999-2000 anyway] and implemented a reverse engineering tool that was state of the art for its time. But this field of research was a dead-end, because Design Patterns are _by definition_, higher-level problem/solution recipes that don’t easily translate to a reusable piece of code in a mainstream programming language. They don’t typically have a standard implementation structure, i.e., the pattern description doesn’t always produce the same concrete OO design, even on a single language/platform. You most often need to adapt the pattern to the needs of your application.

Of course, there are patterns in different levels of abstraction. Picking the well-known GoF patterns, Iterator is one that has a standard implementation in the Java language (java.util.Iterator), C++ (STL iterators) and other modern languages. [You must still create many specializations of the base iterator type, so it’s only white-box reuse.] But this pattern is so simple that its inclusion in the book may only be justified because it was written in the early 90’s. OTOH, the Interpreter pattern has yet to find a single implementation anywhere – there’s a huge range of techniques, none of them are ideal for every case, not even powerful compiler-compilers like JavaCC/ANLTR.

And then you can move beyond GoF and check lattern patterns catalogs, e.g. http://www.eaipatterns.com is one of the best modern references – I can’t recommend this enough; my most complex and successful project owes too much to the fact that I’ve digested this book cover-to-cover because the system needed custom implementations of most of these patterns.

I agree that a powerful macro or metaprogramming facility can increase – at least a little – the set of patterns that can have a standard implementation, even if that’s just a partial implementation. But even these techniques won’t tame most of the patterns. Look at Ruby on Rails, it’s a fine example of using metaprogramming to implement many persistence patterns (http://www.odbms.org/downloads.aspx#odbms_pp). But then, the solution was not solved by simple use of the language’s expressiveness – it required a major new piece of runtime (e.g. ActiveRecord), which implementation is big and complex, so they might just as well have created a brand-new language with all the ORM stuff hardwired as native features… the MOP capability of Ruby is not [in this example] a big deal for application developers, although it is for runtime/middleware developers because it’s easier to write some advanced MOP tricks than create a new compiler. And it’s not yet the Ultimate Implementation of those patterns – we could propose a very different OO/Persistence solution, e.g. a Ruby port of LINQ to SQL.

Er, the GoF book says precisely that you can’t expect to implement a pattern as a single reusable thing.

I agree that not all patterns can have a single implementation, but that’s because some of them touch on active areas of research (e.g. interpreters of all sorts) or are just too vague to be useful ;P

(I can’t comment on Ruby: I haven’t learnt it yet and that it manages to be even slower than CPython is a major strike against it in my eyes. Dammit, if Lua can manage to be both ridiculously small *and* faster than anything else bar compiled code *and* completely portable, there’s no excuse for a less portable interpreter to be slower. Yet they all are. Guessing wildly without data, maybe it’s their bigger cache footprints…)

@Nix: No, the reason why any patterns can’t have a single implementation is the fact that they are DESIGN patterns. You are failing to realize the gap that exists from design to implementation, or more generally, from one level of abstraction to the next (e.g. analysis model to design model). There was a ton of research trying to tame these gaps, e.g. Catalysis (http://www.trireme.u-net.com/catalysis/) that planned to allow full, automatic mapping / binding / traceability between these levels… this research was also steaming hot when I was in the Master, but it is largely forgotten now. And I’m glad it failed, because the idea was that we should create even more complex UML models describing everything from high-level business model down to algorithms, with tons of UML “improvements” to bind everything together so when you make some change in the analysis layer it auto-propagates all way down to code and vice-versa. But even this stuff would not enable automatic generation of flower-level artifacts from higher-level ones, except maybe for restricted cases. Many current CASE tools can actually “generate design patterns”, but that feature is pretty rigid and limited, it doesn’t buy you much. In fact I don’t even use CASE integration to code, either forward or reverse engineering; in fact I only write Design-level UML models when I’m forced by client requirement because it’s not worth it – but I digress…

Osvaldo writes: “the reason why any patterns can’t have a single implementation is the fact that they are DESIGN patterns.”

And yet, some patterns do have a single implementation in some languages — unless you consider the “implementation” so simple as not to count. For example, the Decorator Pattern is trivial enough in Ruby that it’s implemented in one line here at http://pastie.org/12097 — the relative complexity of doing this in other languages seems to come mostly from having to punch careful holes in the type system.

@Mike: When some pattern has a trivial impl in some language (or platform – language+frameworks), this typically happens because their design has “adopted” that pattern. For example, the Java language adopts the prototype pattern (Cloneable / clone()); any OO language&framework adopts the Template Method pattern (polymorphic methods); the Java APIs adopt many many other simple patterns like Iterator, Proxy, Observer, MVC and so on.

Other patterns may be so simple that they often have a standard implementation even without explicit support from the language or frameworks, e.g. Singleton. But even in these apparently trivial cases there is room for variations; for one thing, check out the Lazy Initialization Holder for Singleton:

Smart-ass, concurrent-savvy Java programmers use the code above because it allows the initialization to be lazy, and without risk of concurrent initialization, but without any synchronization cost. You don’t have to synchronize the getInstance() method because Java’s classloading rules will guarantee that the holder class is only initialized once, so its static-init only runs once. (This obviously requires some synchronization within the classloader; but as soon as the Singleton and its Holder are fully initialized, the JVM patches code so no further calls to getInstance() will ever run into ANY overhead of classloading, synchronization or anything.)

The same is valid for most other patterns that are not “officially adopted” by the platform – even when there is a trivial implementation, you’ll often discover that it’s not the single and perhaps not the best implementation. ;-)

I cannot agree with you at all that succinctness is overstated (if, as I assume, you mean overrated). It pains me that Java programmers have been conditioned to believe that it’s tolerable, or even normal, to reflexively write things like

Luckily, my site-owner superpowers meant that I was able to edit Andrew Drucker’s comment, and see it in all its indented glory. Sucks to be the rest of you. (Don’t worry, Andrew, I didn’t change anything!)

…and you create this object with a one-liner like “var pt = Point { x:0, y:1 }”, no constructors required. This example only scratches the capabilities of JavaFX Script’s properties – there are more features like support for visibility control, immutable or init-only fields, and the powerful binding/trigger stuff – all of that with similar conciseness.

Perhaps not, but the library sure is chock-full of them, with date, time, and calendar among the most spectacular failures. I wish Joda Time had been around when I was being frustrated by those atrocities.