Friday, January 11, 2008

Basic Training

I’ve gotten a fair amount of feedback from the Ruby community that my book is an ‘advanced’ Ruby book because I talk about things like open classes, method_missing, DSLs and metaprogramming. I have to say that I think that we Ruby people need to stop describing these techniques as ‘advanced’; all we are doing is scaring people. We need to shout out to the world our little secret: we only use those scary-sounding ‘advanced’ techniques because they make our lives easier. We use them because we are a bunch of lazy sods (as all good programmers are) and they let us write programs that work, with less effort.

Take metaprogramming for example: It’s not easy to write that first metaprogramming program. Metaprogramming is one of those techniques that you need to work at when you first try it. Well, my son is studying algebra, and he occasionally has trouble wrapping his head around ideas like simultaneous equations or open intervals, but that doesn’t make algebra advanced mathematics. Fundamentally the concept of metaprogramming is really quite simple: in order to solve the problem at hand, your program modifies itself at runtime. Anyone who can write code at the keyboard can learn to write programs that write code at runtime. It’s just not that complex. Writing guidance software for a Mars probe, now that’s advanced programming. Metaprogramming, not so much.

This is important because there are a lot of programmers out there who are massively frustrated with trying to solve problems with the traditional programming languages and are looking for an alternative. I think we Ruby folks have a professional responsibility to shout out, “Hey, for many of your problems there is an easier way.” Now that easier way involves some programming techniques that seem strange in the beginning, but once you get used to them they stop being so strange and all you are left with is easier.

-Russ Olsen

One of the great accomplishments of Ruby is that its object and class model bring about a wonderful unity and simplicity. Even things that might seem like they should be hard or obscure are actually very transparent, once you have the hang of how the model works.

Unfortunately, there’s a trend toward drawing an increasingly sharp line between regular programming and “metaprogramming” in Ruby discussions, where metaprogramming is understood to mean… well, I’m not sure what it’s understood to mean, the way it’s getting used in connection with Ruby, and that’s the problem.

There’s no natural separation between programming and metaprogramming in Ruby, and no reason to make life harder by breaking them apart. The thrust of Ruby’s design is to dissolve complexities, so that even things that appear to be “wizardly” or full of “dark magic” actually make perfect sense in terms of a relative small number of underlying language principles.

I’m not saying it’s all a snap to learn. But I do consider it counterproductive to posit some kind of special barrier or fortification surrounding a particular set of Ruby programming techniques. Learning Ruby isn’t like scaling a mountain. It’s more like exploring a plain, with interesting features and a distant but very attractive horizon. One thing leads to another, but not in a way that requires you to fight gravity to get there.

-David Black

You might be inclined to think that metaprogramming is another hacker word and was first overheard in private phone calls between fax machines. Honest to God, I am here to tell you that it is stranger than that. Metaprogramming began with taking drugs in the company of dolphins.

In the sixties, a prolific scientist named John C. Lilly began experimenting with his own senses, to uncover the workings of his body. I can relate to this. I do this frequently when I am standing in the middle of a road holding a pie or when I am hiding inside a cathedral. I pause to examine my self. This has proven to be nigh impossible. I have filled three ruled pages with algebraic notation, none of which has explained anything. The pie, incidentally, has been very easy to express mathematically.

But the scientist Lilly went about his experiments otherwise. He ingested LSD in the company of dolphins. Often in a dark, woeful isolation tank full of warm salt water. Pretty bleak. But it was science! (Lest you think him criminal: until 1966, LSD was supplied by Sandoz Laboratories to any interested scientists, free of charge.)

Drugs, dolphins and deprivation. Which led to Lilly’s foray into things meta. He wrote books on mental programming, comparing humans and computers. You may choose to ingest any substance you want during this next quote - most likely you’re reaching for the grain of salt - but I assure you that there’s no Grateful Dead show on the lawn and no ravers in the basement.

When one learns to learn, one is making models, using symbols, analogizing, making metaphors, in short, inventing and using language, mathematics, art, politics, business, etc. At the critical brain (cortex) size, languages and its consequences appear. To avoid the necessity of repeating learning to learn, symbols, metaphors, models each time, I symbolize the underlying idea in these operations as metaprogramming.

-John C. Lilly, Programming and Metaprogramming in the Human Biocomputer, New York, 1972.

To that end, you could say programming itself is a meta-language. All code speaks the language of action, of a plan which hasn’t been played yet, but shortly will. Stage directions for the players inside your machine. I’ve waxed sentimental on this before.

But now we’re advancing our study, venturing into metaprogramming, but don’t sweat it, it’s still just the Ruby you’ve seen already.

-why the lucky stiff

Telling people that metaprogramming isn't that hard is a public service, but it's kind of like telling people to read SICP: anyone who will listen when you say it was probably going to figure it out for themselves sooner or later anyway. SICP has 82 5-star reviews on Amazon, 53 1-star reviews, and virtually nothing in between. Of course two of the five-star reviews come from Paul Graham and Peter Norvig.

Some of the reviewers complain that SICP doesn't teach the basics of OO design, and so on. In a sense they are right. The book doesn't directly tell you how to design and write an object-oriented program using the subset of object-oriented principles that show up in the syntax of Java or C++. Rather, the book tells you what those principles are, how they came to be selected as worthwhile, how they can be implemented from the ground up, and how a different combination of principles might be more appropriate for a particular problem. This approach requires you to understand the range of possibilities, and to think about trade-offs as you go through the design process.

Programming is a craft that is subject to frequent failure: many projects are started and abandoned because the designers do not have the flexibility, experience and understanding to come up with a suitable design and implementation. SICP gives you an approach that will succeed, but it is an approach based on principles and wisdom, not on a checklist. If you don't understand the principles, or if you are the kind of person who wants to be given a cookbook of what to do rather than to think creatively, or if you only want to work on problems that are pretty much like the problem you worked on last time, then this approach will not work for you. There are other approaches that will be more reproducible for a limited range of simple problems, but there is no better way than SICP to learn how to address the truly hard problems.

-Peter Norvig

SICP is a great book for beginners, as long as what they're beginning to do goes beyond cut and paste.

Metaprogramming is not an advanced technique, unless you treat "advanced" and "new" as synonyms.