C++ is growing, and I am a bit disappointed.
I heard recently that the working group is considering how to add garbage collection to the C++ standard. This is a bad idea. The C language was all about writing low-level code, and did this job well. The C++ language should have been the introduction of some new ideas into C without changing the nature of the language.
If you ignore the right bits then C++ is exactly a better C. If you need to write code that allows you exact low-level control and extreme performance, then C/C++ is a good tool. Not every application needs this kind control, and so you want to pick a higher-level language in which to express your solutions.
Garbage collection is a great idea, but does not belong in a language for writing low-level code. Unfortunately there are bits in C++ that should not be there, and this looks to be another addition to an already overstuffed bag.
How to explain this has bothered me. The answer seems to lie at the intersection of a series of notions.
- Complex languages have “dusty corners” where behavior differs.
- Compilers should translate between machine independent notation to machine dependent executable code.
- First class languages are extensible.
- Minimalist design.
Quite a ways back the guy in the next office was part of a group working on one of the first compilers for Ada. When he ran into problems where the solution was unclear, he would call me over and we would try to work out the most reasonable solution. Now recall that at the time Ada was meant to be a model of the most carefully designed and rigorously defined programming language. The Ada language was also stuffed full of all the coolest features of the day. In implementing the Ada compiler we found the complexity of the language introduced quite a few dusty corners where more than one behavior could be reasonable, and it was up to the compiler writer to choose the most reasonable (hopefully after careful thought).
Clearly there was something not quite right. Differing behaviors in different implementations is not a good thing.
Today with ready communication via email and Internet we might have gotten in contact with the language designer, and sought clarification. The reference manual describing the Ada language was already pretty thick and hard to digest. Cleaning out all the dusty corners would have made the manual thicker and even more difficult to read.
The job of a compiler
Recall that the original purpose of a compiler was to translate from a human readable notion into executable machine code. Writing in machine code was a drag. Assembly code was better but still a drag, and not at all portable.
When moving your code from one machine to another you would like the compiled code to behave the same. The more the implementation in the compiler differs from one machine to another, the greater the chance that some decision in the compiler code will cause the behavior of the generated code to differ.
First class languages and shared implementations
The templates in C++ are essentially very fancy macros. Note that the interpretation of templates into expanded C++ code should be entirely machine independent, and must be the same across compilers. Historically we have seen a lot of trouble with C++ template code behaving differently with different compilers.
Since compilers are all about translating machine independent notation into machine specific code, why is the code for templates built into the compiler?
In Lisp there are lots of examples of things like templates in C++. The key difference is that in Lisp the code for interpreting templates is also written in Lisp. Note that the implementation is not buried in the compiler. Note that the Lisp code can be moved to another Lisp system (discounting the effect of dialects) and can be expected to behave the same everywhere.
Instead of trying to find more things to add, might it not be better to look for things to take away? Not many folks remember the Algol-68 experience (it is a bit before my time even). I do like the approach Wirth took with the Pascal/Modula-2/Oberon family, in looking to build the least possible into the compiler.
Eh - somehow I doubt this explanation is at all as clear as I would like…