Tuesday, November 15, 2005

Challenging Java

There seem to be two completely divergent perspectives on programming languages and tools: one, coming primarily from industry, is currently focused primarily on "conventional" (i.e., not Smalltalk) object oriented languages, XML, XML-based frameworks, visual basic, SQL, etc. The other, coming primarily from academia, focuses primarily on research languages like SML, OCaml, Scheme, Haskell, etc., and on things like new type systems and tricks. Frequently, I find it frustrating that there's less interaction between the two, and a recent article on O'Reilly's OnJava about "four technologies to watch" to replace Java in the mainstream is a perfect example.

Article link.

The first thing that bugs me is his confusion about the value of dynamic programming. It's certainly true that dynamic programming has its proponents, and they would be happy to claim it has advantages[1], his examples miss the point completely.

Example 1:

class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!")
}
}


vs.

puts "Hello, world."

It's certainly true that the second block of code -- written in Ruby -- is shorter than the first. However, this has nothing to do with whether or not "With Ruby, types are dynamic, so you don't have to declare them." The corresponding Haskell (which is about as strongly typed as you can get) is:

main = putStrLn "Hello, world."

His next example is equally classic: a Fibonacci function:
class Fib {
public static void main (String args[]) {
int x1 = 0;
int x2 = 1;
int total = 1;
for (int i=0; i<10; i++) {
System.out.println(total);
total = x1+x2;
x1 = x2;
x2 = total;
}
}
}


vs.


x1, x2 = 0, 1
10.times do
puts x2
x1, x2 = x2, x1+x2
end

Again, the Ruby is much shorter than the Java, but it has nothing to do with Java's static typing. The corresponding Haskell is

main = print $ take 10 (gen 0 1)
where gen x y = y : gen y (x + y)


The code is certainly not intuitive from the perspective of a conventional object-oriented language. But, at the same time, 10.times do is not necessarily any more intuitive to anyone not familiar with Smalltalk.

Neither of these examples really have anything to do with dynamic typing. They certainly address places where Java's syntax is more verbose than Ruby's, but the same terseness is perfectly expressable using statically typed systems (even type systems much more strongly typed than Java). This kind of basic confusion over terminology is a poor start to any discussion of programming language tools and terminology.

The remainder of the article, while not as blatantly wrong, does nothing to highlight anything particularly new in programming languages. Continuations are an old game in all functional languages, metaprogramming has been part of LISP and Scheme since the beginning (and is still very much around in Haskell, although in a different form), and I'm not even sure why he's excited about "conventions" instead of "configurations." While I'm happy to see XML start to lose it's position as the supposed be-all and end-all of data representations, I'm not sure it's a major world event either way.

More than anything else, this article highlights the way one toolkit -- Ruby on Rails -- can capture the mindset of most of the industrial programming world. Nothing in Rails is particularly new and different -- it mainly seems to be a clever hybrid of Scheme and Smalltalk -- but it's come in a new, exciting presentation. This seems to suggest two things:

First, for industrial programmers, it should suggest that the world of programming language research is a fertile one for new ideas. Unfortunately, it's not likely to, as long as articles like the one linked up above don't actually credit the true source of these ideas. As nice as it is to see continuations and meta-programming finally making their way closer to the programming mainstream, it's unlikely that this really heralds a new era of cross-over ideas, especially as long as the ideas that do cross over continue to be shrouded in the same object-oriented ideas that haven't worked for the past fifteen years or so.[2]

Second, for academic programmers (and others interested in research languages), it suggests that all it really takes to get their languages plenty of mainstream notice is one well-designed, timely framework. Unfortunately, most academic programmers are either employed doing something else, or put their spare time into other pet projects. While most of those projects are valuable, it's worth wondering how much more attention (and help) they would get with a wider market for the result.

The truth is, there's plenty of room for ideas to cross between research and production languages, even if the next version of Office isn't likely to be written in Haskell. Someone just needs to try.[3]

[1] As may have become obvious, I am not one of those people.
[2] Oh look, my next topic!
[3] Not me, of course. You!

5 diversions:

Michael said...

On the subject of "dynamic" type systems: You left a square-bracket reference after the word "advantages", but didn't follow up on that. Did you have a particular target in mind? Paul Graham, perhaps?

The examples in that article do take advantage of the dynamism of the type system, although not in a very interesting way. He creates a new class without specifying its constituency, apart from what it inherits. To this, he adds some components, and due to the magic of manifest typing, nothing bad happens. This is not really rocket science, but it does work as advertised; despite the fact that the type couldn't have been inferred statically.

As I see it, one of the principal holdbacks of the strongly statically typed research languages such as SML/OCaml and Miranda/Haskell is that they have traditionally had a hard time with incremental development. It's not impossible to fix that, but so far, that hasn't been a priority for the creators of those languages. The fundamental disconnect between the "industrial" languages and the "research" languages is that the industrial languages target the exact problems their users have, whereas the research languages ask their users to think differently about their problems, in the hopes of obtaining greater generality.

It's not that the two sides couldn't work together, but the motivation is hard to find. Hell, I take it as a pretty good sign that lexically-scoped functions have finally become mainstream, thanks to the popularity of Python, JavaScript, and Ruby. It's a step in the right direction, at least. And, although that article managed to mention continuations without even breathing the word "Scheme", that might well be next.

Monadic programming might take a bit longer. ;-)

Trevion said...

Michael -

Hopefully some of your concerns have been addressed now that I got around to finishing that rant.

The examples later - that rely on discovering the properties of things at run time - do take advantage of dynamic typing. (Although, it's worth mentioning, the same thing is quite doable in statically typed languages - Haskell's Data.Dynamic library provides a simple example, and we use a couple of slightly more complicated variations on the idea at aetion.) However, those are in a different section of his article; what bugged me was not so much the triviality of his examples but that nothing about the ones in his "dynamic type" section really used dynamic typing.

I also think that finding a reason to work together isn't as hard as you suggest, although it takes a different perspective than a lot of people seem to have. For a language evangelist, Rails should serve as a nice example of how to get your language into the spotlight (and, for example, even small examples like Pugs, the Perl 6 interpreter written in Haskell, are getting Haskell very good press in a language community that would otherwise have ignored it completely). For people in industry, just as Rails is motivated by some ideas from research computing, the next exciting framework could well be motivated by other ideas from the same source.

Your final point - about monadic programming - is, I think, the most interesting. My next rant (due in two months! (-;) should attress that very issue. Short version: I think it's time to admit that object-oriented programming isn't everything it's cracked up to be, and maybe monads are the answer.

Michael said...

Yes, you addressed most of my points, thanks.

However, I think you may be underestimating (or at least downplaying) the amount of work it takes to turn a good research idea into that "one timely framework" you mentioned. What makes frameworks like Rails so popular isn't that they are particularly clever, it's that they sweep away an enormous amount of mindless tedium from a large class of common programming tasks. That is what really excites people: Reduction of drudgery. As a research goal, that's kind of boring.

What you are describing can be done, but most researchers, even if they did have the time, would not be interested in implementing stuff like that. Even DARPA will usually settle for a proof-of-concept prototype rather than a mature implementation. Maybe one way to achieve better convergence between academia and industry is to create a funding source that pays industrial programmers to implement cool stuff using research results. The transfer could be part of the grant requirement for the research side.

I agree with you that "object-oriented programming isn't everything it's cracked up to be," but whether monads are an answer (clearly) or the answer (not quite so obvious) remains to be seen. :-)

Anonymous said...

Yes, the article you cite is awful.

When you say "... (which is about as strongly typed as you can get)", you probably mean "statically typed". Also, I believe SML/OCaml typically incurs fewer run-time type checks than Haskell, so perhaps ML would be a better counter-example.

Out of interest, the OCaml is:

print_endline "Hello, world."

and:

let rec fib = function
| 0 | 1 -> 1
| n -> fib(n-2) + fib(n-1) in
fib 10

The SML is:

print "Hello, world."

and:

fun fib 0 = 1
| fib 1 = 1
| fib n = fib(n-2) + fib(n-1);
fib 10;

The latter example uses a different algorithm, not that it makes much difference in this case.

Cheers,
Jon Harrop.

Michael said...

This article by Joel Spolsky is tangentially relevant to your topic here. If nothing else, his partially tongue-in-cheek pleint suggests that there is hope for strong static type systems in weeding out the dross from among the programmers of tomorrow. :-)