This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: Turtles all the way down
Feed Title: Avi Bryant
Feed URL: http://smallthought.com/avi/?feed=rss2
Feed Description: HREF Considered Harmful
Ian Bicking points to Jim Weirich's list of Ten Things a Java Programmer Should Know About Ruby. Ian's general conclusion is that most of what is said about Ruby applies just as well to Python: small differences in philosophy aside, the two languages and their implementations are at roughly the same level. Although I personally do prefer Ruby to Python, I have to agree. However, I believe that Smalltalk is one level up from either of them, and here's why: the one thing that a Ruby (or Python) programmer should know about Smalltalk is, it's all written in Smalltalk.
The Ruby distribution comes with a large amount of C code implementing the underlying language and library semantics: a parser, an interpreter, regular expressions, arrays, hash tables, a numeric tower, and so on. In some cases, like the parser, this code is kept hidden from the Ruby layer: there's no way with a stock Ruby interpreter to get at a Ruby parse tree from Ruby code. This makes certain tools much harder to write - the RDoc documentation generator, for example, has to include its own lexer because it can't access the one that comes with Ruby. It also makes the language much harder to extend, since any change to the way the parser works has to be done in C, and any code that relied on these changes wouldn't run on anybody else's Ruby installation.
In other cases, like Array or Hash, you have what looks from the outside like a Ruby class, but the implementation is actually in C. The way in which this is implemented causes some subtle problems: for example, although you can subclass Array and override its methods, or just redefine a method on Array itself, this will only affect Ruby code - the original C implementation, which doesn't go through Ruby's dispatch mechanisms, will continue to call the superclass version of that method.
I don't know Python's internals anywhere near as well as I know Ruby's, but I suspect that at least some of the above applies to Python as well; certainly, there's a lot of C code in that camp as well. In Smalltalk, however, the only thing that's in C is a tiny virtual machine that understands a very simple set of bytecodes - it knows about pushing and popping objects from the stack, accessing indexed slots, blocks, and method dispatch. What it doesn't know anything about is the language syntax, standard library, compiler, debugger, profiler, thread scheduler, exception system, and so on, and so on - all of these things are implemented in Smalltalk. You want to change the way Array works everywhere in the system, well, find the appropriate Smalltalk code and change it. You want to extend the syntax of the language, subclass Compiler or write your own - the bytecode spec is easy to target. Have an idea for a new way to debug? There's plenty of code you can look at in the current Debugger, Process, and Stack classes to help you along, and when you're done just modify Exception to bring up your debugger instead of the standard one. The language doesn't support continuations and you want to add them? No problem; 10 lines of code and you're there.
This may sound like an academic quibble, like a desire for purity for its own sake, but the fact is that the tools available on a Smalltalk system, like the Refactoring Browser, the Debugger (which takes "edit-and-continue" farther than many people can imagine), the various inspectors and explorers and profilers are much, much better than those available for the "scripting" languages like Ruby. I would argue that a large part of the reason for this is the open, accessible, and extensible nature of the system: nobody wants to write those tools in C, and in Smalltalk, you don't have to.
Note that I'm necessarily talking about implementations here, not language specs: clearly in JRuby, the implementation is in Java instead of C, and clearly you could implement the Ruby language with a Smalltalk-style VM (hopefully one with a Smalltalk-style JIT as well, which would bring a 20x or so speed increase to the current Ruby interpreter). But really what I'm talking about is a philosophical difference, not a technical one: to Smalltalkers, it's essential that as much of a system as possible be implemented in Smalltalk, whereas this simply isn't a priority for the scripting language community, and it's the priorities rather than the individual implementations that draw me to Smalltalk.