next-big-thing
The Next Big Thing
When Joel Spolsky talked here at the Amazon Dev Conference, I thought it was just about the coolest and most enlightening talk about programming I'd ever heard. I was a bit disappointed to hear other folks saying: "yeah, it was funny, but I didn't really get all that much out of it."
Everything he said was important. His talk was about the importance of designing things to be beautiful, simple, appealing. He used a lot of consumer products as examples, but his points all apply to things you do every day, including service design and even writing individual functions. Everything you write is going to be read and used by other people, and they don't want to look at a big mess. Even if it's a working, bug-free, high-performing big mess.
Put another way, correctness and performance aren't the only important concerns when you write code. Aesthetics matter, too. Just like they do with writing prose or (speaking strictly out of my butt here) poetry.
During his talk, Joel told a story about a psychological trick your mind plays on you. I've forgotten the term he used, but the gist of it is that you tend to associate your immediate surroundings and frame of mind with something you're experiencing (such as a movie), and it colors your perception of it. Heavily.
One of Joel's examples was indeed watching a movie. He pointed out that if you have to go to the bathroom really bad, and you're sandwiched between (or behind) two movie-theater-challenged people, then you probably won't like the movie anywhere near as much.
I can tell you this — I really didn't care for Forrest Gump. Everyone else loved it: moms, pops, kids, insurance salesmen, car thieves; it didn't matter who you were, you loved the movie Forrest Gump. Not me, though. When everyone else was crying at the end, I was also crying, but it was because I had to go to the bathroom worse than ever before in my whole life. Plus, I came to the theater late, and wound up sitting in that one seat in the front row over on the very far left, by the emergency-exit door, and my neck had a horrible crick from staring up and to the right at Forrest's distorted face. I hated that frigging movie.
The point? If you allow irritations to creep into your software or your user interface, it doesn't matter how "good" it is; people will be irritated by it.
Setting Expectations
Another nasty trick your mind plays on you is related to your expectations. The higher your expectations for something, the harder it is for that thing to measure up — even if it's actually quite cool. You can even use blatant reverse-psychology on yourself (telling yourself something will be awful) and wind up liking it better. Like Joel's other examples, this mind-trick applies just as much to programming and interface design as it does to, say, telling friends about movies. When you deliver things, you want to try to set expectations low.
As one interesting and significant use case, let's talk about Java's new "smart for-loop". I don't know if that's what they're calling it in the docs anymore, but all the pre-Tiger marketing definitely called it a smart for-loop.
So: why is it smart? Well, Java has this sort of oddball non-orthogonal situation with its type system. Java has four different "kinds" of types. Up until Tiger, it had these three:
Primitive types: longs, shorts, booleans, ints, outs, whatever. They map more or less to machine types, assuming the machine is whatever was popular back in the early 90's when Java was being designed.
Classes, which are the primary mechanism for extending the language.
Arrays, which are this weird hybrid type that was introduced to make it easy to port C and C++ code to Java. But they're really just a gross hack, and everyone knows it and codes around it. You can't make arrays immutable, and you can't subclass them, and there's only modest syntactic support for them, and reflecting on them is painful, and they're basically an example of the Big Pile O' Crap design pattern. But we love them anyway.
That's "all" Java had until Tiger (aka Java 1.5, aka Java 5) came out. As if that weren't bad enough. The problem, of course, with having different types of types is that all of the code you write, now and forever, has to be prepared to deal with each type-type differently. So you get interfaces like this lovely one. Scroll down to the Method Summary, and looky looky, there are 76 actual methods in the class, but only 10 distinct pieces of functionality. Go ahead, just try to convince me that doesn't suck.
Java programmers often hear about Ruby and say: "But does Ruby have static type tags?" I'm semi-happy to report that it doesn't. I'm convinced the ideal solution is what Lisp (and, oddly enough, Groovy) does — you can omit them or include them as you see fit. I may talk more about that in this rant if I don't pass out first. If not, then p'raps in some future blog. In any case, given a choice between Java's broken system and Ruby's lack of a system, I'm now firmly in favor of Ruby's approach. Freedom of expression matters more to me than a little extra static checking. But again, that's really best left for another blog.
In any case, just to make things worse, Java 5 added a new kind of type, called an enum. They're sort of like C enumerations, but they can also have methods. Which makes them sort of like Java classes, but you can't instantiate them, and you can't have one enum type inherit from another enum type, so you can't have polymorphic methods, nor can you declare an enumeration heirarchy. So they're not really like classes at all, they more like... useless is the word that comes to mind.
Worse than useless, in fact: they don't intrinsically increase Java's expressive power, and they add in Yet Another Case for your generalized code to have to handle. Java 5's enums are an example of a design pattern known as an Even Bigger Pile of Crap That Makes Java Arrays Look Pretty Good By Comparison.
Non-Essential Complexity
I'm beginning to wonder whether the much-hailed Java 5 is in fact a death-knell in disguise for Java. It used to be the case that you could know pretty much everything there is to know about Java without too much effort. But almost nobody understands the new generics — I mean all their ins and outs. Sure, I've read the papers, you've read the papers, and we all thought: gosh, I'm really going to have to buckle down and understand all the ins and outs someday, when I really need to know that stuff.
It's been, what, a year and a half now, and I still don't know anyone personally who's an expert on Java Generics. All I know is that a bunch of research papers have been published, issuing dire warnings about the provable incorrectness of Java's approach to generics, and how they damage the type system, and blah blah blah. Whatever. I just wish I understood them well enough to know, off the top of my head, which wildcard to use if I'm declaring some new generic class.
You know, all that complexity would be totally fine in my book, well worth mastering, if the return on investment were obvious. But it doesn't seem obvious to me. I mean, generics are supposed to make your code more type-safe, but all the type information is "evaporated" and unavailable at runtime, so you can't, via reflection or JavaBean APIs, determine whether something is a List or a List<List<String>> or a List<SomeClassUnavailableOnYourSystem>. It may be more "statically" type-safe, whatever that means, but my program does actually have to run someday, and then, when it really matters, it doesn't help me at all.
And generics are supposed to make the code less verbose, by eliminating all those narrowing-conversion casts we had to do when taking objects out of containers. But... I've written a fair amount of Java 5 code now, and it doesn't appear to have helped with the verbosity problem. Now all my interface signatures have to pass around these complicated looking angle-brackets, and the code is actually (in my opinion) a little harder to read.
Sure, when I go back to pre-Tiger code, I find myself looking at a HashMap and thinking: of what? a HashMap of what??, so I'll be the first to admit, it takes some of the guesswork out of reading code. But at what cost? Now I have to read (and write) code that looks like this:
public SortedMap<ArrayList<MBeanServerInvocationHandler>> getFoo() {
SortedMap<ArrayList<MBeanServerInvocationHandler>> foo =
new SortedMap<ArrayList<MBeanServerInvocationHandler>>();
foo.doSomething();
return foo;
}
I mean, gosh. Is there some computation happening in there somewhere?
So Java generics haven't made my code less verbose, and they haven't really made my systems a lot more type-safe. They're certainly a little more type-safe, and I've even found one bug in some preexisting code where I was putting the wrong type of object into a container; porting to the new generics helped me find the bug. But it was just that one time. The more Java 5 generics code I pile into my system, the less valuable that lone success story seems. The overall value generics have brought me is... well, it's debatable. I'm not sold on them, and I bet you aren't either.
This side-discussion has gotten rather long, but this issue really is nagging at me. With Java 5, the Java platform appears to have crossed some invisible threshold, teetering into the land of C++ and Perl, where the language complexity is too high for the value you're getting.
Like, it's failing the ROI test.
Java became popular precisely because it was the right language at the right time: back in 1996, Java offered simpler, more natural ways of expressing your computations. Other languages did this too, but Java hit a magical "sweet spot" of having just the right values for the following function inputs:
Expressiveness (so there was an actual reason to switch)
Simplicity (so large numbers of programmers could learn it quickly)
Performance (so it wouldn't be too expensive to switch)
These are a few of the inputs to the magical function that determines that the most popular language will be — or what the next big language will be, whenever we hit that mid-decade point where there's a language revolution. It was C in 1975, C++ in 1985, Java in 1995, and... woah, look at the time! Is it 2005 already?
Of course, the inputs above are necessary but not sufficient. You need two more ingredients for the recipe for Language Revolution:
People have to be in pain. Lots of people, lots of pain. They don't necessarily even need to realize they're in pain; they may be totally in love with their current language. But the pain has to be there, and your new language has to take most of that pain away. Enough to keep them happy for another decade or so, anyway.
There has to be marketing, and buzz: the catalysts that fuel the reaction.
So, like, here we are, roughly a year away from Java's 10-year anniversary, and I don't know about you, but I'm starting to feel a lot of pain when I program in Java. It's all sort of subconscious; it just feels like I'm working too hard, even though I know the language pretty well. I can "think" in Java, so I can code for long periods without reference to the API docs — which enables me to get into that wonderful programming-trance you need to be in for maximum productivity. But I'm getting kind of tired of the awkward way Java forces you to say many very common things, and the much-heralded Java 5 "Tiger" release didn't help. Not enough, anyway.
And I used to know Java really well, but I'm not so sure anymore. The new class-metadata thing is interesting, but I'm not 100% sure where I'd use it. It doesn't immediately solve most of the problems I encounter day-to-day with my Java code. I can certainly see how it'd be useful for storing Aspects in the class file (for AOP), or keeping javadoc documentation around at runtime, but those are big one-offs, and mostly for use by tools, not programmers. What are the new or improved design patterns I can use personally now that Java has class metadata? I have to believe it's more useful than just documentation and assertions, and that it can actually improve my designs, and my implementations of those designs. But hey, it is called "metadata", so maybe my expectations are too high.
But at least the metadata stuff wasn't too hard to learn. I read a good article about it, and it all made immediate sense. Exciting. See a feature, learn the feature, (maybe) use the feature. Wasn't too hard. Generics, though — that's still really murky for me, even after several days of study and months of casual use. And enums added all this type-complexity without helping me at all.
And then there's the "Smart" for-loop.
The So-Called Smart For-Loop
This feature really does help cut code verbosity. So much so that it's really the main focus of my rant today. The basic idea is that before Java 5, when iterating through an array or collection, you had to do this:
Iterator it = myCollection.iterator();
while (it.hasNext()) {
MyObject foo = (MyObject) it.next();
// do something with foo
}
or, if it was an array, this:
for (int i = 0; i < myArray.length; i++) {
MyObject foo = myArray[i];
// do something with foo
}
The new "smart" for-loop in Java 5 lets you say both of them like this:
for (MyObject foo : myArrayOrCollection) {
// do something with foo
}
It may not seem like much of a savings from these little examples, but you'd be surprised — just converting to this syntax can shave 10% off the size of a typical code base.
Why is that? Why would such a seemingly minor syntactic sugaring make a detectable blip, let alone a 2-digit percentage blip, in everyday Java code?
I'll tell you why! And it's important, as it ties this whole drunken rant together, at least to some extent. The reason has to do with first-class functions.
Coach vs. First Class
I used to do international flights a lot, back at Geoworks on the big project we were doing with H.P. Singapore. Flying coach inside the States isn't a big difference from first-class, but on international flights, it's like a throwback to 15th-century feudal monarchies, where there are the Kings and the Peasants. (Or a throwback to 21st-century tech companies, where there are the pre-IPO and post-IPO employees.)
On Singapore Airlines, and I can assure you that this is the Honest, Verifiable Truth, seniority amongst flight attendants is determined entirely by how good-looking you are. In coach, you get the Ordinary-Looking flight attendants. In business class, you get the Good-Looking ones, and those folks in the handful of first-class lounges (it's hard to call them "seats", since they recline completely flat) get the Supermodels. Not kidding. And they admit it, too, if you ask the airline personnel about it.
On United Airlines, seniority is determined by, well, seniority. This provides an interesting and memorable contrast when you're switching between UA and Singapore Air in either direction, because evidently at United, "seniority" is closely tied to "bitterness" and "surliness".
On both airlines, biz-class gets the good seats, and First Class gets the Truly Amazing Seats that cost Thousands of Dollars — but they really are worth it, if you can afford that kind of money, because first-class travellers arrive at their vacation destinations bright and cheery and ready to adventure, whereas Coach passengers arrive ready to sleep for a week.
In short, there's a big difference between First Class and Not First Class. And it's every bit as true in programming languages. Programming is filled with "concepts", and some of them are more visible than others, because some get to be first-class language entities. For instance, in Java and C++, a Class is a first-class entity. In C, you may be coding something that's very similar to a class, but you have to squint at it to see its outline, because there's no syntax or even keywords for what you're doing.
Very real programming concepts range in programmer-visibility from patently obvious (e.g. function parameters, exception handlers) to almost entirely invisible (e.g. the current stack depth, or the direction the stack is growing, or amount of heap storage consumed by a given class in the system). You can sometimes query these invisible concepts using API calls, but even then, they're rarely available as "first-class" entities. There's no Java class called CurrentStackDepth, or for that matter, even CurrentExecutionStack (also known as a continuation). There's some visibility into these things, but only just enough for some security checks and for debugging — nothing that you could use for writing your own scheduler, for instance.
Which actually matters, a lot, when you're trying to do high-performance concurrent code, but we'll save that for another blog.
In any case, you might think a function is a pretty central concept to programming (and computing in general). And you'd be right! But functions aren't first-class entities in Java. You can't "refer" to a function directly, e.g. to pass it as a parameter so it can be invoked later. Because functions are first-class concepts without first-class support, this skews Java code into a definite "shape" — a set of idioms that are unique to Java, and which are causing programmers pain without their realizing it.
Visitaters
What's a function again? Well, pulling out my giant, dusty math book and chasing the moths away, I see that a function is a mapping of one set of values to another set. One definite output for each possible input. Domain, range. Yes, it's all coming back now.
Programming languages almost always give you a shorthand for writing functions with multiple arguments and (sometimes) multiple return values, although this is to some extent syntactic sugar for composing multiple functions of one arg each.
But whatever. You know what a function is. It can have inputs, outputs, and side-effects. It's executed by some process or thread that has a call-stack, which is how functions call and return. It's the Way Things Work in "modern" programming languages. We don't use GOTO very much anymore.
Functions are often applied to sets of values. Arbitrary example: selection (or "querying") — you want to apply a filter function to every element of some set, and return a set of the elements that passed the filter. Or perhaps you need to examine each element of a collection, aggregating some statistic over the elements (e.g. the sum of the lengths of the string keys in a map).
You do this kind of thing all the time, regardless of which language you're using. You process database result sets, bytes from input streams, tags in XML documents, command-line parameters... the list goes on and on. A lot of everyday programming is about "processing" collections of similar elements.
How do you do this kind of thing in Java? Well, you have two basic options: the Visitor pattern and the Iterator pattern. With Visitor, you send your function off to the collection, which applies your function to each element in some order. When it's done, you've visited everyone. If your function needs to accumulate or aggregate some results, it needs a place to put them. With Iterator, you ask the collection for each element in turn, in a loop, and process each element returned by the Iterator.
In Java, neither Visitor nor Iterator is a first-class concept. Iterator appears to be the closer of the two, because it's reified as an interface, namely java.util.Iterator, that any collection can implement. Most Java collections implement the iterator pattern, and some other Java classes do too. But a rather surprising number of collection or collection-like classes do NOT implement java.util.Iterator, including:
java arrays, which ARE collections but are NOT real classes, so they don't have their own methods. You have to loop through them using a positional index.
java.lang.String and java.lang.CharSequence — both seemingly collections of characters, but you can't iterate over them using the standard Iterator idiom.
java.sql.ResultSet, which has its own unique cursor-based approach to iterating through the results.
java.io.InputStream, which is logically a sequence of bytes, and you loop through them just like any other collection — but not using java.util.Iterator!
In fact, I bet you could think of a whole bunch of logical sequence types that aren't supported by Java's Iterator pattern. Each of them has its own uniquely stupidly different way of accessing it. You could write Iterator classes for each of them, but you couldn't actually attach your class in any way to the class you're wrapping — it's not like you could write a class that lets you call iterator() on a java.io.InputStream directly. You'd have to write some other class, InputStreamIteratorFactory most likely, that accepted different input streams and returned the appropriate Iterator type — with none of the benefits of polymorphism or, in fact, object-orientation. Cripes, Java programmers might as well be writing in C, for all the OO support they really get.
And Visitor — well, forget about that, there isn't even an interface for it. Gotta roll your own.
"Smart" for-loop to the rescue!
So Java 5 came along and saved the day, right? Well... sort of, if you're generous. The so-called "smart" for-loop actually provides two useful and different services:
It allows you to do less (keyboard) typing when iterating over collections. And all else being equal, shorter code is better code.
It unifies iteration over Collections and primitive arrays — the syntax is the same for both of them. It's not as if they've made arrays first-class objects, but they've taken a teeny step towards making the language slightly more uniform. Less to remember! Easier to read! You don't care if the underlying sequence is an array or java.util.Collection (nor should you, since for design flexibility you should be able to change from one to the other without impacting everyone using your collection.)
That's great! Happy happy, joy, joy. Don't you just love the "smart" for-loop? Lots of Java programmers do.
You see, Visitor is a real pain to implement in Java, because to do it "properly" you need to declare at least one class, often more (e.g. a factory of some sort). And you still have to use the Iterator pattern underneath, since you can't change the Java Collections classes to accept your Visitor object. So people don't do it very often.
Your only other option for processing elements of a collection is to iterate through them. That is why the "smart" for-loop cuts Java code by a noticeable percentage: because in Java, the Iterator pattern is the easiest among a fairly limited set of options for processing a collection. So Java programmers use it a LOT. Hence, introducing special syntax for it was a big win, Java-wise.
However...
What if you want to do something different on the last iteration of the loop? You know, like print a newline instead of a space. Or skip printing the last comma in some list you're serializing.
Well, unfortunately you can't do that with the new "smart" for-loop, because it doesn't give you any access to the underlying iterator. It can't, really, because for arrays, there is no underlying iterator. So there's effectively no way to know how far along you are in the iteration, using the new for-loop syntax.
And you can't delete elements either, again because you have no way to access the underlying Iterator. If you want to delete an element when using the new "smart" for-loop syntax, you have two equally bad options:
Go for it! Delete the element, cross your fingers, and hope the collection supports deleting elements while a concurrent traversal is happening (in this case, yours.) Most of them don't, and they throw an exception. If yours does support it, then you're especially unlucky, because down the road someone could change it and cause a bug that gets you paged.
Create another collection to hold all the elements scheduled for deletion, then apply the deletions after you're done with the iteration. Ugh.
And of course, the new "smart" for-loop doesn't work on any of the other collection-like classes: streams, result sets, strings, or anything else that's not an array or a class that implements java.util.Iterator.
I dunno about you, but I'm starting to think that "smart" might not have been the best way to set my expectations about this new Java feature. I'm thinking that maybe a better name, a more appropriate name, would have been the "stupid" for-loop. That might have adequately prepared me for the massive quantities of important functionality it fails to exhibit.
And here's the kicker: we had to wait almost ten years for this feature.
That, friends, is what's wrong with Java. It's a symptom of a massive problem, one that's causing millions of Java programmers pain without their necessarily even realizing it. The problem is: well, it's Java. It's not like it's one thing, or even a few things. It's the whole thing:
the defeatable, non-orthogonal type system with four kinds of types (with generic type information thrown away at runtime)
the syntax you can't change, so that no matter how you might wish for a for-loop that's really and truly smart, you'll never get one, and there's nothing you personally can ever do about it.
the immutable classes, which prevent you from doing anything remotely resembling Object-Oriented Programming, ironically enough, because you can't add methods to existing classes.
...and so on. It's a long list.
If you're a C/C++/Perl programmer thinking "hah! I'm sure glad I'm not using Java", I can tell you this: I'd still rather be using Java than C++ or Perl.
But at this point, None of the Above is starting to sound like the most attractive option of all.
It's Decade O'Clock
You wanna know what I think? I think Java, seemingly at the very crescendo of its fame and glory, is actually about to get blown away by some other language. And it's going to happen in about a year, with the new language actually becoming the most popular language on the planet by 2008 or so. By then, it'll feel like it happened almost overnight, just as C, C++, Perl and Java all took off like wildfire.
OK. What language is it? Might as well get prepared...
Unfortunately, I don't know. I'd pay a pretty penny to know, so I could start writing in it right now, feeling confident that it'll be a bet I won't regret later. After all, the most popular language will start getting libraries and docs and performance enhancements, all the benefits of being a First-Class language, basically. That's the one you want to bet on.
I can tell you what I think it is. I think it's going to be Ruby. Yup. Not Lisp, not Scheme, not Arc, not Haskell, not OCaml, not Python. Not XML (please, not XML.) Not Perl 6 or C++ 18 or Java 29.
Ruby.
This is just a gut feeling I've been having lately, based on a bunch of circumstantial evidence and educated guesses. Here's what I've got — you be the judge.
First, Ruby's a good language. In fact, it's a great language. It's not the only great language out there, and it's not perfect (no language is). But in order to convince millions of Java and C++ programmers that they were actually in horrible pain, and that it's the cure, it would have to be a pretty darn good language.
(I could get very sidetracked talking about how Ruby is a great language, and how it cures so many of the ills that Java programmers are unaware they're fighting against. But I'll save it for a future blog, because it really is a pretty big topic in its own right. )
Next, Ruby hasn't poisoned the well. I don't think Python can ever be the Next Big Language because it's already been written off by too many programmers. It's fixed some of its problems, and continues to innovate slowly. But Ruby is just screaming along, and it started life with a cleaner design. I think the window of opportunity may be closed for Python.
And Perl — well, I think people have started to realize that they don't want to memorize another gigantic language. They want to do more with less. Big languages are going the way of Big Hair.
Ruby's getting a VM — several of them, in fact; it's being re-architected so it can be retargeted to any of a whole heap o' VMs, including the new Ruby VM, the Java VM, the .NET VM, Parrot, and others too. So Ruby will be ubiquitous, and it will benefit from all the performance enhancements going into the VMs themselves.
I've mentioned Ruby in blogs before, but I've always been rather dismissive of it because its performance has scared even me, and I have Moore's Law tatooed on my ass (the joke's buried down in the first comment on that funny blog entry, FYI.) But with a VM coming, well, who knows. I'm starting to feel hopeful about the future of Ruby's performance.
Ruby's really popular in Japan, and is being funded by (as far as I can tell) not just one, but several Japanese companies, who are sponsoring VM development, library-writing contests, and documentation, and other Ruby-related development.
Inside sources say that O'Reilly (who always have their ear to the ground about this kind of thing) thinks Ruby may be the next big thing, and is gearing up to launch a series of Ruby titles as a sort of precautionary measure. And the Pragmatic Press is allegedly doing the same, independently.
And then there was that Slashdot post a week or two ago about a famous-ish Java programmer who ported his system to Ruby on Rails, and the Ruby version outperformed the Java one by at least 10%, conservatively. But his Ruby code was only as big as the Java version's config file. That kind of story is hard to ignore, and you hear them a lot. It jibes with my own (limited) experience — Ruby's tight. It's basically tied with Haskell as the most concise language I've ever seen.
Finally, Ruby's fairly mature — you can't expect an in-development language (e.g. Perl 6 or Arc) to be the next big thing, unless perhaps it's got heavy sponsorship from a big company willing to invest a lot of money in developing and marketing the language. I doubt anything will come out of Microsoft that's interesting to programmers using Unix or Linux systems. I doubt Sun will support anything that's not Java. And I haven't heard of any others. There's the D language, of course, but it doesn't make programming that much easier than it is in Java already. Ruby code tends to be phenomenally shorter than the corresponding Java code — five to ten times shorter. Noticeable.
Am I 100% sure it's going to be Ruby? Nope. If I were, I'd be hollering at the top of my lungs that people should be using it Right Now for everything they possibly can. But Ruby's still got some issues:
Until the VM is official and stable and supported (basically Ruby 2.0, or "Rite", and I don't know when it's slated to come out), it won't be able to use native threads, let alone HotSpot-style native compilation or other benefits of using a VM.
Ruby doesn't have any particularly special support for distributed computing, a la Gambit Scheme or Erlang, and I think that's a large part of where programmers are feeling their pain right now. Ruby really needs to have support for massive numbers of lightweight "threads" and asynchronous I/O, or it'll never really be appropriate for writing high-performance servers and services.
It needs more libraries. And docs. But so do all up-and-coming new languages, so Ruby's really no worse off here than most challengers, and better than many.
So it's not exactly a sure thing. It's just my hunch.
And why don't I think it's going to be Lisp? Or Haskell? Or any other viable contender? Well, it could be (and any of them would be fine, really), but I just don't think they have the ability to reach the "masses". Heck, Haskell has thus far been unable to reach me, even though I've bashed my thick skull against three or four Haskell books. I "get" it at some level, but it's just so foreign. Same goes for OCaml, actually. And trying to do any sort of I/O or anything... I just haven't been successful at writing a real Haskell or SML/OCaml program. Maybe I'm dumb. Well, that I'm certain of. Maybe I'm just not trying hard enough.
But gosh — with Ruby, I didn't have to try at all. It was easy to install, easy to learn, easy to use. It works the way I expect things should work. And that matters! When it comes right down to it, I'd prefer not to have to bash my head against difficult books in order to express myself in code. So I think Ruby's got them all beat when it comes to ease of user adoption.
Maybe this is all just wishful thinking. I happen to like Ruby, even though I don't have all that much experience with it. There's just something about it... you'll see for yourself if you sit down and just play with it for a few hours, or a few days. Yes, it's got some problems and annoyances, but far fewer than most languages (or so I think.) It's somehow familiar — it borrows most of what you liked about Perl, and has most of what you like about Java, and some interesting things from other languages like Smalltalk and Lisp. But it's not a kitchen sink — contrary to (my) expectations, it turns out to be a tiny, consistent, beautiful little language.
Aesthetics evidently matter quite a bit to Matz, Ruby's inventor.
And Ruby's amazingly powerful. The metaprogramming stuff really does come within spitting distance of what you can do with Lisp macros — basically almost anything except reader macros, so you can't change Ruby's syntax. Other than that, it's almost the same idea. And although Ruby's syntax is more complex than Lisp's, it's far simpler than Java's, so it's quite easy to learn, and read. And write.
We'll see. In the meantime, I'll keep an eye on Ruby, and go back to using my fancy new Stupid For-Loop that Sun has so graciously deigned to provide me after a nine-year wait. And maybe one of these days I'll figure out those new generics. I really ought to get to that someday... after all, if I wait too long, they could be obsolete before I really get a chance to use them.
Eh. Maybe I'll just hold off. I've got better things to spend my brain on.
(Published April 19, 2005)
Comments
Alas, it doesn't look like Rite will be coming out any time soon.
A short while ago, Don Box apparently said something like,
"If I could wave a magic wand, we would all just use Ruby", where "we" presumably means MSFT.
(http://a9.com/don-box%20ruby%20microsoft)
Posted by: Andrew W. at April 27, 2005 09:39 PM
"I doubt Sun will support anything that's not Java."
Yesterday (today?) they released the first public spec for Fortress:
http://research.sun.com/projects/plrg/fortress0618.pdf
The existence of the language doesn't prove anything in and of itself, but if they bothered to publish a puff piece about it in Dr. Dobbs, *somebody* wants to market it...
Posted by: Derek U. at April 27, 2005 09:47 PM
Both interesting comments!
Derek, I stand corrected. Fortress looks interesting — I read about half the pdf; I'll look at the rest later this week. It appears to be reasonably well-designed, at first glance. And I'm definitely looking forward to being able to use graphical smileys as variable names.
Remains to be seen whether it "feels" nice when you're using it. OCaml, f'rinstance, is a wonderful language on paper, but makes me feel like a rat running a maze when I try to write anything in it. (For reasons that I think I know how to articulate clearly now — working on another blog about it at some point.)
Anyway, I'd been wondering if having Guy Steele and Richard Gabriel and all those Lisp-y guys at Sun would ever result in anything. I suppose this is it! I'll look at Fortress in more detail ASAP. Thanks for the pointer.
Posted by: Steve Yegge at April 28, 2005 01:12 AM
I have been playing around with Python. While I like it, the performance bothers me, and what bothers me more is that Python-ers aren't bothered by it! And I'm not talking about holistic performance, one major sore point with me and Python is the performance of method calls. If method calls are slow, well guess what, you're more likely NOT to use them, and we all know where that ends up.
So there is this tacit encouragement in Python not to do proper OO encapsulation. You get better performance by accessing and setting properties directly rather than using method calls. I find this really annoying to me. One other issue I have with Python is lack of field definition. It'd be really nice to have a list of fields defined somewhere so I can know what this object stores. And the idea of having custom instances that have different methods than other instances of the same type kind of bothers me, if only for the debugging problems that spawns.
Now I also attended the Joel on Software presentation. One thing that annoyed me was his suggestion that the iPod is only popular because it's cool and that competing systems are better. In this case it is not true, the iPod become popular against more featureful players because it actually worked, its UI was elegant, clean and easy to use and the integration between computers and the player just worked.
But my greater point is this, while I can imagine many programmers would draw back in revulsion at his suggestion that users don't care about the engine, the 'guts' and only care about the shiny surface. I could imagine a developer saying 'this is why users suck, they just don't realize what is important!'. Deriding users because the user interface isnt nice, even though the engine, the guts are perfect.
Now, I have been using Mac OS X for about 3 years now. I am definitely a mac head now, and it's great. One thing I remark on all the time is just how beautiful fonts look. Now one might say I'm being superficial, but on the other side I do spend something like 8-12 hours of my day looking at the screen, so it damn well better look good. Both pleasing, and easy to see.
As for good user interface, now that the graphical user interface is the primary interface with our computers, wouldn't you want an interface that is clean, expresses clear concepts simply and helps you avoid errors? Isn't that a computer's job in fact, to do work so you don't have to? Having a UI that does exactly what you want, and it anticipates your needs and prevents you from making dumb mistakes is a joy. This is my joy of using OS X :-)
BTW, I really love Boost.Python.
Posted by: Ryan R. at April 28, 2005 10:51 PM