MayJuneJuly

The latest: We’re expecting! The due date is the middle of February. First ultrasound looks good. Robin’s pretty sick a lot of the time, but there’s only a month left in the first trimester, and we’re hoping the nausea settles down after the first trimester like it did with Alan. She’s a lot sicker this time, and thinks that maybe that means we have a girl. Hard to say, but we’ll find out!

Alan keeps growing. He’s at the just-shy-of-terrible-twos now and exerting his independence by means of tantrum. (Lord help you if you want to change his diaper, or if you leave the room without his permission.) We took him to the zoo for the first time last weekend, and he was far more interested in the carousel than the animals. Ah, well. He recently learned that he can stack his alphabet blocks into towers, which has been highly entertaining to watch. Still no speech yet except for going “nyaah” when he sees a cat (it’s his “meow”), but with any luck, he’ll at least figure out “Mommy” and “Daddy” soon. He certainly knows what we’re saying, and nods (and waves his arms) and shakes his head (and waves his arms) to indicate “yes” and “no.”

What’s new in Smile-land? Back in April, I started rewriting the interpreter in C. It was never going to be fast enough in C#, and I always knew a C or C++ port would be necessary. I rejected C++ after a few attempts (more thoughts on that below). So far — well, I have a garbage collector and a working String object and a bunch of unit tests and that’s about it for the last three months. I only get an hour here or there at best to work on it. But Ben recently challenged me to have a minimally-usable interpreter by Christmas, and that’s put a little more fire under my butt to do something about it.

On C++

I rejected C++ because C++ is C++.

I coded a heck of a lot of C++ over the years, and I know the language well (or at least the pre-C++11 versions of it). And at first I attempted to start in C++. But C++ just doesn’t lend itself well to good code: It solves all the wrong problems. You end up spending so much time writing code to correctly manage types that you never get anything useful done, and on top of that, you have to decide which C++ you’re going to code in: Just super-C? C-with-classes? Actually use virtual functions and inheritance? Gonna try to stay const-correct? And don’t forget those copy constructors and operator overloads! You know to use nullptr and typename and not NULL and class anymore, right? And what about templates? While you’re at it, template-metaprogramming can do amazing things at compile-time! After all, angle brackets are the new hotness, right!?

I originally started the new Smile code in C++, and found myself spending more time trying to answer how the C++ code would be structured and which parts of the language I would use than I did actually implementing anything. So I tossed it, and went to C. C has its limitations, to be sure, but it’s well-known, predictable, portable everywhere (I consider that very important), and very, very fast.

With proper discipline, it doesn’t take any more effort to code in C than it does in C++; all the same idioms are implementable in some way, should you need them — which, as it turns out, you mostly don’t. Most functions aren’t virtual. Most classes don’t inherit. Most cleanup rules are either trivial function calls or require something significantly more complex than a C++ destructor anyway. C++ works well for certain special cases, like reference counting, but if you have a real garbage collector (reference counting doesn’t count as a real GC, since it can’t recover cycles), you don’t need most of those special cases.

So I’ve been coding in C, and after a half decade of C# and a prior decade of C++, it’s incredibly refreshing. Stuff just works. I really missed everything just being real data or pointers (no “magic references;” and what the hell is a “int &&x” declaration in the new C++ standard anyway?). There’s a one-to-one mapping between what you write and what you get. FILE is way, way better than iostreams. The compiles are stupid-crazy-fast. And I sort-of had forgotten just how powerful macros are. The more I work in C, the more I find myself rejecting C++ as a really fascinating but really failed experiment: There are some things in C++ that are pretty cool, but they’re not worth the extreme cost they exact on the design of your software. If you need OO and “fast enough,” you can use Java and C#. If you need “really fast,” you can code in C. (And maybe Rust. I’d give Rust more time to mature, but it’s a project worth paying attention to.)

(And if you need “highly capable,” you can code in Smile. That is, after all, the whole point of this exercise: The extreme flexibility and power of Lisp and Smalltalk in a much-more-palatable package.)

There are a few things in C I wish I had from C++, but the list is damn short, and most of them are things that don’t really violate Ritchie’s design:

  • The ability to declare local variables anywhere inside a function before their usage, for example, is way overdue, and my biggest single feature request. Having the compiler “lift” them to the nearest open curly brace wouldn’t be rocket science to implement. That said, being forced to declare them at the top does a good job of indicating just how much stack space your function is going to eat, so there is some value in that arbitrary restriction.
  • Supporting “//” for comments is way overdue (so overdue that most compilers already have it).
  • A proper “inline” keyword for functions (again, many compilers have “__inline” or “__inline__” or something like it).
  • Anonymous (unnamed) structs and unions (again, many compilers have this too).
  • Default trailing arguments (constexpr only) on function prototypes. This doesn’t complicate the language much, and it would really simplify a lot of over-complicated function declarations where you’re declaring three different functions just so you can omit some trailing parameters.

But, hey, whatever. We’ve lived with those limitations since the ’70s, and they didn’t exactly stop the Linux kernel or GCC or ten-tons-of-everything-and-the-kitchen-sink from being written over the years. C, for its faults, still does “wear well as one’s experience with it grows.”