I find it very helpful to understand why language features exist. If they’re just handed to you on a platter by a college professor, you tend to develop a mythology around the language and to say “there’s some really important reason for this language feature that the smart people who created the language understand and that I don’t, so I’ll just take it on faith.” And at some point, faith-based acceptance of language features is a liability; it prevents you from being able to analyze and understand what’s going on. In this keynote, I look at a number of features and examine how they are implemented in different languages, and why.Here’s an example: object creation. In C, you declare variables and the compiler creates stack space for you (uninitialized, containing garbage unless you initialize it). But if you want to do it dynamically, you must use the malloc() and free() standard library functions, and carefully perform all the initialization and cleanup by hand. If you forget, you have memory leaks and similar disasters, which happened frequently.
Because malloc() and free() were “only” library functions, and confusing and scary at that, they often didn’t get taught in basic programming classes like they should have. And when programmers needed to allocate lots of memory, instead of learning about and dealing with these functions they would often (I kid you not) just allocate huge arrays of global variables, more than they ever thought they’d need. The program seemed to work, and no one would ever exceed those bounds anyway — so when it did happen, years later, the program would break and some poor sod would have to go in and puzzle it out.
Stroustrup decided that dynamic allocation needed to be easier and safer — it needed to be brought into the core of the language and not relegated to library functions. And it needed to be coupled with the same guaranteed initialization and cleanup that constructors and destructors provide for all objects.
The problem was the same millstone that dogged all C++ decisions: backward compatibility with C. Ideally, stack allocation of objects could simply have been discarded. But C compatibility required stack allocation, so there needed to be some way to distinguish heap objects from stack objects. To solve this problem, the new keyword was appropriated from Smalltalk. To create a stack object, you simply declare it, as in Cat x; or, with arguments, Cat x(“mittens”);. To create a heap object, you use new, as in new Cat x; or new Cat x(“mittens”);. Given the constraints, this is an elegant and consistent solution.
Enter Java, after deciding that everything C++ is badly done and overly complex. The irony here is that Java could and did make the decision to throw away stack allocation (pointedly ignoring the debacle of primitives, which I’ve addressed elsewhere). And since all objects are allocated on the heap, there’s no need to distinguish between stack and heap allocation. They could easily have said Cat x = Cat() or Cat x = Cat(“mittens”). Or even better, incorporated type inference to eliminate the repetition (but that — and other features like closures — would have taken “too long” so we are stuck with the mediocre version of Java instead; type inference has been discussed but I will lay odds it won’t happen. And shouldn’t, given the problems in adding new features to Java).
Guido Van Rossum (creator of Python) took a minimalist approach — the oft-lambasted use of whitespace is an example of how clean he wanted the language. Since the new keyword wasn’t necessary, he left it out, so you say x = Cat(“mittens”). Ruby could have also used this approach, but one of Ruby’s main constraints is that it follows Smalltalk as much as possible, so in Ruby you say x = Cat.new(“mittens”) (here’s a nice introduction to Ruby). But Java made a point of dissing the C++ way of doing things, so the inclusion of the new keyword is a mystery. My guess, after studying decisions made in the rest of the language, is that it just never occurred to them that they could get away without it.
So that’s what I mean about language archaeology. I have a list of other features for similar analysis during the keynote. I hope that people will come away with a better perspective on language design, and a more critical thought process when they are learning programming languages.
Take a look!