The Art of the Witch Hunt
This entry is a satirical reply to Josh's comment on my last blog, and it makes a lot of fun of his comment. I wrote and published this entirely without Josh's knowledge or consent, which just goes to show how cool I think he is, based on the various email interactions we've had in the past. A less saintly person than Josh would simply have marched in and shot me. Just in case it's not clear, "satirical" means it's all a BIG JOKE, albeit one intended to illustrate a point in a memorable way. Josh and I discuss it in the comments below.
Josh's "Xurf" comment on my "Scheming is Believing" blog entry has been bugging me for days.
He seems to have missed many of my central points, but that's not what's been bothering me. Not at all, in fact. You see, if he had simply commented: "Steve, I didn't understand a damned thing you wrote," I would have nodded in sympathetic agreement and replied: "Yeah, I suck at explaining things. It's my fault, not yours."
I even predicted, right there in the blog, that most folks wouldn't understand my points. It turns out you can't just hear an explanation of Lisp and say: "Oh, I get it now. Of course! I'm going to just drop all my other favorite languages now." It's taken me years to finally figure out what all the hullabaloo is all about. Other, far better writers have tried explaining the merits of Lisp, and for the most part they've failed utterly to convince mainstream audiences. So I knew I wasn't going to be able to do any better.
Hence, misunderstandings weren't what was bugging me about Josh's comment. But what the heck was bugging me? It took me quite a while to figure it out.
I finally realized, after wrestling with trying to construct a short, cogent response to Josh's comments, that his arguments are 100% pure, naked, unadulterated FUD. I don't think I've seen such brilliant FUD in a very long time, parading right there in out the open like that. Now that I see it, I can only stand in awe of its power. It's a really useful technique, because it's easy to do, and it's next to impossible to argue with.
FUD, in case you're unfamiliar with the term, is an acronym for "Fear, Uncertainty, and Doubt". It's what people do when they want to bash on something because they're scared of it. It's the kind of bashing that aims directly for a killing blow, without screwing around.
Josh is a super smart guy, of course. His code for the ADJ challenge last month was clear and brilliant, and it won him 2nd place. And his "Xurf" comment sounds rather tongue-in-cheek, all things considered. It may have even been satire, in which case he gets extra kudos. Regardless, many folks will probably read his comment, spot the logical fallacies, and not give it another thought.
Unfortunately, Josh wielded his FUD with such technical mastery that it puts me in a bit of a bind, because many people may not spot the fallacies, and his stone-throwing could ultimately have a larger impact than all that stuff I wrote.
What to do, what to do?
Since Josh was performing what amounts to a magic trick, I think the key is to show people what's happening behind the smoke and mirrors.
Wars and witch hunts
I mentioned in my "Scheming is Believing" blog that people hate Lisp so much, they'll put it on trial and burn it at the stake.
I've written in the past a bit about the mechanics of programming-language religion, about how the hatred stems from fear: not some trumped-up little wimpy fear, like the fear of spiders, or the fear of accidentally ingesting eggplant, both of which I suffer from. No, I mean real fear, the Big One, fear of Death. And it leads programmers of different languages to hate one another.
That hate manifests itself in different ways, depending on the situation.
Big, mainstream, popular languages like C++, Java and Perl go to war with each other. That's just the way it has to work. If you hate a group of people and you want them to cease to exist, or at least give up their heathen views and join you, then you have to go subdue or kill them. But if there are a whole bunch of them, then it means it'll be a long, protracted war. Still, you've gotta do what you've gotta do, right?
With Lisp, I knew the blind hate would manifest itself as a witch hunt. There aren't enough Lisp hackers at Amazon to fight a war. There are few enough, in fact, that it's far more efficient to burn them at the stake in a mini-genocide, laws be damned and all that.
At Google, it would be a war. That's because Google hires a lot of famously smart people. It turns out that a large percentage of famously smart people — by which I mean people who've made their mark on computer science, or who invented tools and languages you love, like Java and GCC and Unix and AspectJ and so on — are Lisp hackers. So Google has a bunch of them. Too many to burn at the stake, I think. It would at least be a major skirmish to try to eliminate all of them there.
However, here at Amazon, it was obvious that introducing Lisp would lead to a witch hunt, which is precisely why I spent the whole last section of the blog warning people not to use Lisp here.
But as right as I was, I didn't expect the witch hunt to start quite so soon — in the second blog comment, no less. FUD and witch hunts are kissing cousins, of course, and Josh is clearly out to burn that damned witch named Lisp.
Well, guess what: I'm not really that interested in defending Lisp. I like plenty of other languages. So burn her.
However, seeing as you are all grown-up engineers, I must insist that you be able to recognize a witch hunt when you see or participate in one. That way you can conduct it properly.
Conducting Technical Witch Hunts
A good witch hunt of course needs someone to kick it off, using the time-honored call to arms: "Burn her! She's a witch!" It helps to throw a rock or two, just to prove that she's a obviously witch, because she's bleeding, or because it didn't kill her, or whatever. Plus it feels good.
That last point might seem trivial, but rest assured that it's essential. You're trying to turn a group of ordinary, possibly complacent people into an angry mob. There are really only three rules you need to remember:
Make people happy.
Think about emotions.
Obsess over aesthetics.
Throwing a rock or two at the alleged witch is a very stylish way to get those emotions flowing, and it really does feel good.
It's very important to steer clear of anything resembling logic. Kirk and Spock taught us all about how poorly emotion and logic understand one another. The most important element of getting a good witch hunt started is to speak right to those primal emotions, the most useful one being fear.
My advice: irrational fears are the best ones to target, because, well, they're irrational. You don't need to do much in the way of explaining; an irrational fear will just fire right up with almost no provocation, especially in a mob.
Josh has given us a most excellent example (almost textbook, really) of how it's properly done in the programming world. Let's deconstruct his arguments a bit, so as to gain a keener insight into the basic mechanisms of getting people riled up for a burnin'. You never know when this skill may come in handy!
Step #1: Scare People
Remember, think about those mob emotions. People won't shed all restraint and take up the pitch and pitchforks unless they're either really scared or really angry.
You have to pick one or the other and run with it. When the parasympathetic nervous system kicks in, it's "flight or fight", and you don't want half your mob running off in fear. A good bait-and-switch tactic is to start them off scared, then hand them an easy outlet for smashing things to make the fear go away forever.
Let's take a look at Josh's masterful introduction:
> Xurf kuzl farq lozy!
> You don't understand? Well, I'm taking advantage of a hypothetical
> framework for extending English in fundamental ways. Unbeknownst to
> you, "kuzl" is part of a new grammatical construct that makes
> expressing recursive ideas much more natural.
Notice that he's picked a pretty good opening move, going after the Fear of the Unknown. Powerful one. For many people, it's even stronger than the fear of eating eggplant at a fancy dinner and projectile vomiting 30 feet onto the bridesmaids.
Josh has deftly mixed it in with another, more subtle fear: the fear of looking dumb in front of other people. "You don't understand?" is a beautiful attention-getter, and sets the stage for many of his later arguments and rebuttals.
In technical witch hunts, it's very important to be articulate, even eloquent, because tech people are smart. That's a key difference between technical witch hunts and the more traditional kind. Josh has hit this one right on the head. His writing style flows smoothly and has the unmistakable (and un-fakeable) ring of intelligence behind it.
Step #2: Then Confuse Them
There are of course all sorts of valid objections to his opening line of reasoning, including:
you can make stupidly unreadable identifiers in any language.
people extend English in ungrammatical ways all the time; e.g. "Joe is bar raising on this interview", yet it doesn't seem to bother anyone.
a language extension wouldn't exactly be "unbeknownst" to anyone; the engineer would get it reviewed and document it, just like any new API.
Those kinds of objections are potentially dangerous to your end goal of smelling the burning witch's clothing, hair, and fat, then kicking her charcoaled corpse into the pond.
Hence, it's essential that you don't dwell too long on any of your arguments. As soon as you make a point, you'd best rush on to the next one, before anyone has a chance to think too hard about the previous one.
> I have heard enough smart people describe the profundity of their
> experiences with LISP to believe that it's a lot more awesome than I
> currently realize. But when the selling point is how radically you can
> redefine the language, I feel like they miss the value of language
> consistency, which translates into being able to read foreign code and
> know what the hell is going on.
The classic logical fallacies are old chestnuts that can be valuable tools when you're instigating a witch hunt.
Josh cleverly chooses to employ an Inductive Fallacy — a cute meta-reference to his hypothetical framework for expressing recursion, from the previous paragraph. His False Analogy, which has a certain intuitive appeal (as logical fallacies often do), is in his use of the "which translates to" conjunction.
We all know that language consistency does not, in fact, translate automatically to being able to read "foreign code" (whatever that means) and know what's going on with it. The concerns are orthogonal: you can find easy-to-understand foreign code written in inconsistent languages, and hard-to-understand foreign code written in highly consistent languages.
But that's a hard thing to think about! You have to come up with counter-examples, think through what he's saying logically, and so on. That's why it's so perfect for scaring people. He's directed the reader's attention squarely on their fear of not being able to read someone else's code.
And just in case anyone in the mob is really alert, Josh avoids defining terms like "foreign" and "consistency", giving his accusation many possible meanings. Makes it harder to reason about. Most people won't even bother; he's got them thinking about that fear, and now he just needs to twist the knife some more.
Step #3: Steal Your Enemy's Arguments
> In your first Java example, you wrote one line of code, and with that
> alone you were able to explain exactly what Java does to evaluate that
> line. Any experienced Java programmer in the world would be able to
> tell you the same thing, just by looking at that one line.
Oooh, there's some expert misdirection going on here. Penn and Teller would be proud. You have to focus the mob on something simple — one line of code will do nicely, and get them to agree that yes, they understood that line of code.
The trick is to soothe them a bit. Emotions, you know — important. Get them to make the inductive leap that because they understand that one line of code, there's no possible way anyone could write Java code that they wouldn't understand.
And the beauty of his example is that he's appropriated *my* example. I used that line of code to illustrate in a perfect, canonical, one-line way, that Java is utterly screwed without a macro system.
It was such a beautiful illustration! There's no way to make it perform well, and you have to poop that same line out all over your code base, wherever you want tracing to occur, and even a partial fix requires you to add a bunch of fragile references to a debugging flag. It was one of the foundational cornerstones of my argument.
Josh very intelligently went for blood there. He took my line of code, waved it in the mob's face, and made it his own. "See? You understand this line of code! Lisp will ruin it for you!"
I'm telling you: I've been wrestling with Josh's comments for days, on and off, and I now have nothing but the purest admiration for the brutal effectiveness of his methods. Lisp is going down. It doesn't stand a chance against the mob, given an effective enough stone-thrower.
Step #4: Twist the Knife of Uncertainty
> Now pretend that you're up at 2AM trying to debug some system that you
> just inherited, the guy who wrote it is no longer with the company,
> you know he's a smart guy but sometimes too clever for his own
> good. And you have somehow localized the problem to this line:
> (make-it-happen (widget-functor asin) (map make-it-happen data))
There's the knife-twisting I mentioned earlier. It's expertly done; you have to marvel at his skill. He leads you along a path you're secretly terrified of, because it used to happen at Amazon, and then shows you a line of vague-looking Lisp-ish code, one that could actually be expressed virtually identically in any language at Amazon, and he's got you: you don't understand it!
It doesn't matter that he made the example up, or that in reality you'd be able to see all the other code around it. It doesn't matter that Lisp debuggers can expand the macro for you, which shows you precisely what's happening to a degree that isn't possible in C++ or Java (because the macro expansion is Lisp, which you can understand, rather than bytecode or assembly, which you cannot). It doesn't matter that this kind of thing happens all the time, and you just deal with it: roll back the service, say the other engineer was a dork, and life goes on.
None of that matters because he's playing up to your fears. It's like that dream where you go to school, only to discover you've forgotten to wear any clothes. Fears are irrational. Best way to get a witch hunt started.
> I don't know enough crazy things you can do with LISP to come up with
> a plausible example, but you get the idea. How much other code will
> you have to read to even discover what *sort* of thing this does?
Handwaving is my personal favorite technique. Make sure to make it clear you haven't bothered to research the issue, but that it's OK to express concerns about it nonetheless.
Rhetorical questions are also very solid techniques. They have no answer, lacking any sort of context, so while the mob stands there pondering what the hell the question means, you can rush right to your next point.
Step #5: Get Up on the Soapbox
> I believe there is value in language consistency, namely that it makes
> it very transparent what your code is actually doing. Not that you
> necessarily understand *why* it's doing what it's doing, but you at
> least know *what* it's doing.
Soapboxing: another fine way to get emotions flowing. How can one argue with him? It sounds logical enough. Consistency, as we pointed out before, does NOT translate to transparency, and in fact my whole point was that consistency doesn't do squat for you if your language forces you to speak like a preschooler; all consistency does is make it take 10 pages to say what should have been said in one line.
No, the soapbox is really getting ready for his grand conclusion, which is that we need to burn that witch! You have to climb up on the soapbox and say something, preferably some appeal to emotion, to start getting people ready for action.
By saying "I believe there is value in language consistency", he's of course implying that Lisp people do not harbor such simple, homespun, all-American values. Remember, take care not to ask it as a question! A Lisper might say: "Uh, yeah, I believe in language consistency too; that's why I use a language that has only one syntactic form. Plus, like, um, I'm a programmer, and I have all the same issues with other peoples' code that you do." No! You must never let the witch speak, and never let people think for a moment that she's human.
The best way is soapboxing: motherhood and apple-pie speeches that imply the witch is in fact the spawn of the devil. Works like a charm.
Step #6: Go for the Kill
> If LISP really gives you the expressive power to implement Perl with
> LISP macros, then I hardly see how it could be consistent enough to
> allow a large group of people to share/maintain LISP code. Unless you
> restrain yourself from making these deep extensions to the language
Ah, it's so beautiful. I don't know about you, but *I* am certainly ready to go burn me a witch. He's invoked the Fear of Perl. Never saw that one coming. Scares me half to death to think about it. Burn her!
> but then why waste your time writing clunky things like (setq x 1)
> when you could just write x = 1?
WOW! What a finale! He's simultaneously invoked the Fear of Wasting Time and the Fear of Parentheses in one clever example! I think a round of applause is in order.
Josh: you are a genius. Fortunately I knew you were joking, and you know that *I* am joking. I wonder how many other people knew?
(Published February 10, 2005)
Man, Steve, we need to go out for coffee or something. If you knew me, I don't think you could have misconstrued the intent of my comment so badly.
I don't read your blog and comment to antagonize you or others, I read it because it draws me in almost every time and makes me think. You think about the same kinds of things I think about, and you challenge my opinions (for example, I am a big C++ fan and don't like Java).
I didn't write that comment to make people hate LISP, and I don't know if I've ever been accused of spreading FUD before. I've surely never been accused of leading a witch hunt! I wish now that I had prefaced my comment by saying "I totally grant you that LISP is unmatchably powerful, flexible, and mind-bending. I don't get it yet, but I have faith that there is an 'aha' moment somewhere in my future."
Questioning the merits of LISP wasn't the point of my comment. I didn't say "I didn't understand a damned thing you wrote," because my comment presupposed that every great thing you said about LISP is true. In a nutshell, my comment said "that sounds really great, but how would you respond to this one specific objection?"
I could have written a totally straightforward expression of my point. "LISP is undoubtedly very flexible, but I have had a long-standing concern about this flexibility. If the point of LISP is to always mold it to your problem domain; if LISP is "pure DNA" as you say; if LISP is so flexible that you could implement Perl with it, does LISP have the consistency that we come to expect from less flexible languages? I think this consistency is an important characteristic of more common languages, especially in large projects."
But then I thought "no one reads Steve's blog because it's straightforward. They read it because he's colorful, and writes in hyperbole, and alludes to life at Amazon, and weaves around until he finally arrives at his point at the end. I can try that.
Sometimes I have to clench my teeth a bit when you write things like "Ever notice how "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn" and "Protected abstract virtual typedef'd copy constructor function" sound identical underwater?" Because I really think C++ rocks. But I realize that you have your opinions and I have mine. Was I any more unfair to LISP than you are to C++?
We should chat sometime, agree to disagree about C++ and Java, agree to hate Perl and love Ruby, and agree to disagree about Emacs vs. VIM. :) I think we could be friends.
Posted by: Josh H. at February 10, 2005 05:35 PM
Hopefully the above doesn't seem like I'm trying to duck the accusations of FUD. Let me make at least a minimal defense of my intellectual honesty.
I was not claiming that you can immediately *understand* code written in any other language. I tried to specifically disavow this claim when I said "Not that you necessarily understand *why* it's doing what it's doing, but you at least know *what* it's doing." The mechanics of other languages are fairly transparent. Brian Mahar tried to refute this claim by citing this C++ code:
if ( (*self->mark_funcs[d])(self, changed_field_number) != SUCCESS)
But in my opinion, this illustrates my point. Here's what I know:
self is a reference to the enclosing object
it has a member variable mark_funcs, which is an array of function pointers.
this line calls a function from a function pointer in that table, at offset d, with the parameters self and changed_field_number
it then compares the result to success
if success was not equal to SUCCESS, the enclosing method will return FAILURE
Because I know all these things, I would say the mechanics of C++ are fairly transparent. I may have no idea why this class has an array of function pointers, or what those functions do, but I *do* know the mechanics of what that line does, just by looking at that one line of code.
An honest question: can I know as much about the mechanics of what LISP does from isolated code examples?
Your argument that you can easily expand LISP macros into what they actually mean is an effective rebuttal to this concern.
You read "I believe there is value in language consistency" with totally the wrong tone. It was not to imply "LISP people do not believe this," it was to avoid implying "my value is more than opinion, it's fact!" I'm really pretty humble when it comes to expressing my values.
I didn't make up the Perl reference — I was alluding to your comment that "With compiler macros, you can pretty much change anything you like about the language. With enough effort, a suitably crazy person could emulate Perl in Lisp using nothing but macros." And I was asking: "if this is true, does this mean that 'reading LISP' is equivalent to 'reading whatever language the author has chosen to implement with LISP'?"
And the point of the "finale" was: if you are *not* using LISP to do crazy things like implement new grammatical constructs, why would you use LISP as a plain imperative language, when its syntax compared to other plain imperative languages is pretty clunky? Remember when you commented at your EMACS talk that elisp hadn't exactly made your life easy when you were implementing your typing tutor? That's what I'm appealing to.
Hope you no longer think I'm morally bankrupt.
Posted by: Josh H. at February 10, 2005 07:29 PM
Hi Josh! I figured you might be the first commenter. :-)
Of course I don't think you're morally bankrupt. It's not YOU I'm worried about, if'n you know what I mean. You're one of the Good Guys. Heck, I'd never in a million years have put you up on stage for a dissection like that had I not already been utterly convinced that you're smart and cool.
The problem is that your comment (which I do think was quite clever, and I've tried to respond in kind) was... impenetrable. A veritable Gordian Knot, as it were. It has assumptions folded on assumptions, and jumps from issue to issue in a way that reminds me of famous unanswerable questions like "Which is faster — to Cleveland, or by bus?" and "Do you still beat your wife?"
To unpack everything, set it up neatly, and answer your questions (both the explicit and implied ones), really takes about 10x as much space as your comment itself. But if you ask a seemingly simple question, and I have to give a long-winded, blustery, complicated answer, it makes me look like I'm either evading your question or I'm incompetent. Sorta human nature.
These are really, REALLY complex issues we're talking about. You know that, I know that — but can we really be sure every new hire at our company knows that? Early in my career I was only too ready to jump on the bandwagon if someone was cheerleading. Or witch-hunting.
In short, you put me on the spot, and I decided to have fun with it. :) And I have to say, regardless of whether people thought it was funny, I laughed hysterically when I thought of using Joel Spolsky's three laws of UI design as the rules for a proper witch hunt. Har.
I'll buy the first coffee, and maybe you can tell me some cool stuff about C++.
Posted by: Steve Yegge at February 10, 2005 09:21 PM