== Quote from Walter Bright ([EMAIL PROTECTED])'s article > I wish it were possible to have a language with just a small set of > features that can do everything. C++'s problem is it can approximately > do everything but with a boatload of gotcha's, like a const system that > almost works but doesn't deliver. Java threw out too much.
Agreed. The problem with C++ isn't so much that it's just complex. Its problem is that its complexity comes in the form of lots of cruft inherited from C, from technological limitations that existed during its development but are no longer relevant and from just plain bad design decisions that can't be undone without massively breaking backwards compatibility. Java went so far in the quest for simplicity that, since the irreducible complexity of a program has to go somewhere, it ends up being expressed in lots of "design patterns" that should be replaced by language features. Worse yet, Java's solution to C++'s complexity is to force one level of abstraction, namely the class, to fit every problem, no matter how awkward that is. For example, let's say I wanted to write a simple function to sort an array by an arbitrary comparison function in Java: void sort(ArrayList<T> stuff, Comp comp) {...} I have to define an interface called Comp and a class that inherits from it, which under the hood is using arrays of function pointers, because Java doesn't trust me with function pointers. This is called abstraction inversion. Most programs have some subproblems that are pretty run-of-the-mill and should just be solved in the most expedient way possible, and others that require more thought, either to make them generic enough or fast enough. Mixing languages in one project is generally a pain, especially if you want to do so on a fine-grained level. Therefore, the thing D gets right that few if any other languages do is that it has a "keep it simple, stupid" layer for the run-of-the-mill subproblems and a ridiculously complex but powerful boot-with-a-gun-built-in layer for the more challenging ones, *in one language*. The simple layer includes builtin arrays, builtin associative arrays, garbage collection, the ~= operator, good string handling, and a reasonably powerful standard lib, at least if you're using either Tango or the D2 version of Phobos. The complex layer includes templates, manual memory management, unions, casting, operator overloading, and inline assembler. The way I usually write my D code is to use the complex layer for relatively generic, performance-critical code near the bottom of my abstraction hierarchy, and then use the simple layer in the higher levels of my programs to call this code. That way, I get C++-like performance when I need it, and Python-like safety and ease of coding when I don't. Frankly, this works amazingly well. Being able to do this in one language, so seamlessly, is a perfect example of useful complexity.