Why Racket? Why Lisp?

This book was made pos­si­ble by a pub­lish­ing sys­tem called Pollen. I cre­ated Pollen with the Racket pro­gram­ming lan­guage. Racket is a de­scen­dant of Scheme, which in turn is a de­scen­dant of Lisp.

So while Racket is not Lisp (in the spe­cific Com­mon Lisp sense), it is a Lisp (in the fa­mil­ial sense) which means that its core ideas—and core virtues—are shared with Lisp. So talk­ing about Racket means talk­ing about Lisp.

In prac­ti­cal pro­gram­ming projects, Lisps are rare, and Racket es­pe­cially so. Thus, be­fore I em­barked on my Lisp ad­ven­ture, I wanted to un­der­stand the costs & ben­e­fits of us­ing a Lisp. Why do Lisps have such a great rep­u­ta­tion, but so few users? Was I see­ing some­thing every­one else missed? Or did they know some­thing I didn’t? To find out, I read what­ever I could find about Lisps, in­clud­ing Paul Gra­ham’s Hack­ers & Painters and Pe­ter Seibel’s Prac­ti­cal Com­mon Lisp. (OK, parts. It’s a big book.)

What I found was plenty of Lisp flat­tery from ex­pert Lisp pro­gram­mers. (Also plenty of Lisp kvetch­ery from its de­trac­tors.) What I didn’t find were sim­ple, per­sua­sive ar­gu­ments in its fa­vor. So here’s why Racket was the right tool for this project, and what I see as the prac­ti­cal virtues of Lisps in general.

I didn’t study com­puter sci­ence in col­lege (though I was a math ma­jor for two years, be­fore switch­ing to de­sign). I’ve never held an of­fi­cial job as a pro­gram­mer. Rather, pro­gram­ming has been a sec­ondary skill I’ve used in my work as a web de­signer, type de­signer, and writer.

These days, I spend an in­creas­ing amount of my time pro­gram­ming. This pro­gram­ming gen­er­ates in­come. So by the sim­plest de­f­i­n­i­tion—does the skill make you money?—I sup­pose I qual­ify as a pro­fes­sional pro­gram­mer. And since most of my pro­gram­ming ef­forts are in Racket, I qual­ify as a pro­fes­sional Racket programmer.

Mind you, I’m not claim­ing that I’m a good pro­gram­mer. (You can de­cide for your­self.) Among the Racket com­mu­nity, which is laden with com­puter-sci­ence PhDs & pro­fes­sors, I (have no choice but to) em­brace my rel­a­tive ig­no­rance. Hence the ti­tle of my talk at Rack­et­Con 2014: Like a Blind Squir­rel in a Fer­rari.

Yet de­spite my flaws as a pro­gram­mer, with Racket I’ve been able to ren­der big­ger ideas into pro­grams more quickly, and with fewer bugs, than any lan­guage I’ve used be­fore (and there have been many—Ba­sic, C, C++, Perl, Java, JavaScript, Python, and oth­ers). Since I haven’t got­ten a brain trans­plant re­cently, there must be some­thing spe­cial about Racket as a language.

Lisp is a lan­guage most pro­gram­mers have heard of, for two rea­sons. First, it’s one of the old­est com­puter lan­guages, in use since 1958. Sec­ond, it’s ac­crued a rep­u­ta­tion as a lan­guage for braini­acs. Orig­i­nally this rep­u­ta­tion arose from its as­so­ci­a­tion with the field of ar­ti­fi­cial in­tel­li­gence. Since then, this rep­u­ta­tion has been main­tained by pe­ri­odic en­dorse­ments from re­spected pro­gram­mers (lat­terly, Eric Ray­mond and Paul Gra­ham) and the en­dur­ing fame of the text­book used in in­tro­duc­tory com­puter-sci­ence courses at MIT, Struc­ture and In­ter­pre­ta­tion of Com­puter Pro­grams (which uses Scheme, and that one I did read start to finish).

But as main­stream pro­gram­ming tools, Lisp and its de­scen­dants have been largely ig­nored. Pop­u­lar­ity of pro­gram­ming lan­guages is tricky to mea­sure, but here’s a sim­ple proxy—let’s count the num­ber of projects cur­rently hosted on GitHub. One could quib­ble about the ac­cu­racy of this method, ex­cept that the re­sults aren’t even close:

LanguageGitHub projects
JavaScript885,467
Java644,711
Ruby622,088
Python432,533
PHP420,913
C218,287
Clojure21,108
Common Lisp6883
Scheme5128
Racket2727

The last four lan­guages are Lisps, and to­gether ac­count for only 35,846 projects. Racket it­self only ac­counts for a small frac­tion of this small fraction.

Pop­u­lar pro­gram­ming lan­guages aren’t nec­es­sar­ily good—look what’s at the top of that list—but un­pop­u­lar lan­guages of­ten have fa­tal flaws that pre­vent wider adop­tion. As I was con­sid­er­ing lan­guages, Racket had a lot to rec­om­mend it. But was there a fa­tal flaw I was over­look­ing? And by com­mit­ting to a Lisp, would I be paint­ing my­self into a cor­ner? I wanted to un­der­stand the risks and benefits.

I said above that Lisp flat­tery is easy to find. The prob­lem with Lisp flat­tery is that it makes sense only to ex­pe­ri­enced Lisp pro­gram­mers. To oth­ers—es­pe­cially those who are try­ing to de­cide whether to learn and use a Lisp—it just comes across as un­sub­stan­ti­ated hoodoo.

For ex­am­ple, in his es­say How to Be­come a Hacker, Eric Ray­mond says “Lisp is worth learn­ing for … the pro­found en­light­en­ment ex­pe­ri­ence you will have when you fi­nally get it. That ex­pe­ri­ence will make you a bet­ter pro­gram­mer for the rest of your days, even if you never ac­tu­ally use Lisp it­self a lot.” Un­for­tu­nately Ray­mond doesn’t fol­low up this claim with a de­scrip­tion of the “en­light­en­ment ex­pe­ri­ence”, nor why it’s “pro­found”, nor how it will im­prove your pro­gram­ming skills generally.

To be fair, Ray­mond’s es­say is not fo­cused on Lisp. But com­pare Beat­ing the Av­er­ages, by Paul Gra­ham, which is. Gra­ham starts off by cit­ing Ray­mond’s com­pli­ment to Lisp and seems ready to make the claim concrete.

In­stead, he breaks it into smaller chunks of flat­tery. “We knew Lisp was a really good lan­guage for writ­ing soft­ware quickly.” Be­cause of what char­ac­ter­is­tics? He doesn’t say, but then de­scribes Lisp as his “se­cret weapon”. OK, so what’s the se­cret? He says “pro­gram­ming lan­guages vary in power”. Fine, but what ex­actly makes Lisp more powerful?

Gra­ham of­fers one con­crete ex­am­ple: Lisp’s macro fa­cil­ity, which he de­scribes as its abil­ity to make “pro­grams that write pro­grams”. Af­ter 18 months us­ing a Lisp lan­guage, I’d agree with Gra­ham that macros are great when you need them. But for some­one new to Lisp lan­guages, they’re not a bread-and-but­ter ben­e­fit. (They only make it to #8 on my list of fa­vorite fea­tures below.)

I was hope­ful when I opened Pe­ter Seibel’s Prac­ti­cal Com­mon Lisp and saw that the in­tro­duc­tion was sub­ti­tled “Why Lisp?” Yes, tell me! Seibel echoes Gra­ham’s claim: “You’ll get more done, faster, us­ing [Lisp] than you would us­ing pretty much any other lan­guage.” OK, but how? Seibel won­ders whether “I like Lisp be­cause of some quirk in the way my brain is wired. It could even be ge­netic, since my dad has it too.” That’s not en­cour­ag­ing to those of us out­side your fam­ily. Ul­ti­mately, he sums up the ap­peal of Lisp by de­scrib­ing it as “the pro­gram­ma­ble pro­gram­ming lan­guage”. But I’ve never used a pro­gram­ma­ble pro­gram­ming lan­guage. Why should I start?

And by the way, when do I get the speed and power you keep promising?

In short—what’s in it for me, now?

This is the fun­da­men­tal ques­tion that Lisp ad­vo­cates have to an­swer for new users. But more of­ten, it’s side­stepped. I’m not pick­ing on Ray­mond or Gra­ham or Seibel. They’re ex­cel­lent writ­ers, and as pro­gram­mers, they’re way out of my league. As I learn more about Lisps, I re­turn to these pieces and they make more sense.

But these pieces are also em­blem­atic of a gen­eral weak­ness of mes­sag­ing about Lisp. I say that not as a rank­ing mem­ber of the Lisp com­mu­nity, but rather as some­one who spent a lot of time seek­ing an an­swer to that fun­da­men­tal ques­tion. I never got it.

Seibel is pass­ing the buck when he says that to un­der­stand the ben­e­fits of Lisp, “you’re go­ing to have to learn some Lisp and see for your­self”. Sure, this method works—us­ing Racket for a few months fi­nally made the ben­e­fits of Lisp clear to me. But it also re­quires an in­vest­ment of about 100–200 hours.

That’s ask­ing too much. If Lisp lan­guages are so great, then it should be pos­si­ble to sum­ma­rize their ben­e­fits in con­cise, prac­ti­cal terms. If Lisp ad­vo­cates refuse to do this, then we shouldn’t be sur­prised when these lan­guages re­main stuck near the bot­tom of the charts.

In a word, ex­pres­sive­ness: the mea­sure of how easy it is to put your ideas into code. For in­stance, an ex­pres­sive lan­guage like Racket lets you write the “Hello world” pro­gram like this:

"Hello world"

Whereas a less ex­pres­sive lan­guage—I won’t name names—re­quires this:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello world");
    }
}

Con­ci­sion is valu­able, but ex­pres­sive­ness also em­bod­ies other qual­i­ties: pre­ci­sion, read­abil­ity, flex­i­bil­ity, po­ten­tial for abstraction.

Com­pared to other lan­guages, Lisps are tremen­dously ex­pres­sive. Like the over­pow­ered Japan­ese mo­tor­cy­cle I once owned, they go where you want, very quickly, with a min­i­mum of in­put. If you’ve rid­den a mo­tor­cy­cle, then you know what I mean. If you haven’t, good news—Lisps are cheaper and safer.

Here’s my rank­ing of the lan­guage fea­tures that have of­fered the most im­me­di­ate value to me, a pro­gram­mer new to the Lisp world. For each, I’ve noted whether it’s a fea­ture of Racket specif­i­cally, or Lisps generally.

  1. Every­thing is an ex­pres­sion. [Lisps] Most pro­gram­ming lan­guages are a com­bi­na­tion of two syn­tac­ti­cally dis­tinct in­gre­di­ents: ex­pres­sions (things that are eval­u­ated to pro­duce a value) and state­ments (things that ex­press an ac­tion). For in­stance, in Python, x = 1 is a state­ment, and (x + 1) is an expression.

    State­ments and ex­pres­sions are dis­tinct be­cause while ex­pres­sions can be nat­u­rally nested with each other, state­ments and ex­pres­sions can­not. For in­stance, in Python, this is still a valid expression:

    (x + (y + 1))

    but this is not:

    (x + (if is_true(): 1 else: 2))

    be­cause the if–else con­di­tional is a state­ment, and can only be used in cer­tain positions.

    By mak­ing every­thing an ex­pres­sion, how­ever, Lisps re­move this lim­i­ta­tion. Since ex­pres­sions are nestable, any­thing in the lan­guage can be com­bined with nearly any­thing else. For in­stance, be­cause an if–else con­di­tional is an ex­pres­sion, you can use it in place of a value:

    (x . + . (if (is_true) 1 2)

    You could also use a con­di­tional in place of an operator:

    (x . (if (wants_sum) + *) . 1)

    You could even nest an­other con­di­tional within that:

    (x . (if ((if (cond) cond_1 cond_2)) ...)

    And so forth. This is a syn­thetic ex­am­ple. The point is not that you’d nec­es­sar­ily want to do this, but that Lisps per­mit it. As a pro­gram­mer, this both sim­pli­fies your work (be­cause every­thing snaps to­gether eas­ily) and ex­pands your pos­si­bil­i­ties (be­cause you can com­bine parts of the lan­guage in un­usual ways if you feel like it).

    It’s sim­i­lar to the ba­sic idea be­hind Le­gos. Other build­ing sets of­fer spe­cial­ized pieces that can only fit to­gether cer­tain ways. But by shar­ing uni­form mea­sure­ments, Lego bricks of­fer max­i­mum pos­si­bil­i­ties for com­bi­na­tions. This ends up be­ing more flex­i­ble & more fun.

    So it is with an ex­pres­sion-based lan­guage. If you find this idea ex­cit­ing, con­grat­u­la­tions—you might be a Lisp pro­gram­mer. (If you find this idea weird and scary, this is a good mo­ment to bail out.)

  2. Every ex­pres­sion is ei­ther a sin­gle value or a list. [Lisps] Sin­gle val­ues are things like num­bers and strings and hash ta­bles. (In Lisps, they’re some­times called atoms.) That part is no big deal.

    The list part, how­ever, is a big deal. In a lan­guage like Python, the list is one data type within the lan­guage. But in Lisps, the list is more like an or­ga­niz­ing prin­ci­ple for every­thing that hap­pens. So yes, you can use the list as a data type. But a func­tion call is also a list. In fact, the source code for the func­tion is a list. Ac­tu­ally, the rest of the pro­gram is too. Lists are every­where. (The fancy CS term for this prop­erty is ho­moiconic­ity.)

    The ben­e­fits of lists are sim­i­lar to that of ex­pres­sions. By bring­ing more of the lan­guage into a con­sis­tent form, more pos­si­bil­i­ties arise for how pieces can be com­bined and manipulated.

    Seibel de­scribes Lisp as a tool for get­ting “more done, faster”. Here, you can start to see why this is so. Lisp lan­guages are im­mensely flex­i­ble and per­mis­sive in how their pieces can be con­nected. This means that the way you think about a pro­gram­ming prob­lem can be quite close to the way you ac­tu­ally pro­gram it. (This is also why Lisps have tra­di­tion­ally ex­celled for pro­to­types and ex­ploratory work.)

    To be fair, get­ting the most out of a Lisp means learn­ing to think more in the Lisp id­iom of lists and ex­pres­sions. So I can see why Seibel says that try­ing it your­self is the best way to be con­vinced of the ben­e­fits. As you get a feel for lists and ex­pres­sions, it does pay in­creas­ing div­i­dends through­out the lan­guage. You see how tiny lines of code can pro­duce epic amounts of work. You also start to ap­pre­ci­ate that even in a well-de­signed lan­guage like Python, you’re spend­ing a lot of time shap­ing your ideas to fit its lim­i­ta­tions, like shav­ing an in­vis­i­ble yak.

  3. Func­tional pro­gram­ming. [Lisps] Yes, I know that other lan­guages of­fer func­tional-pro­gram­ming fea­tures, and that Lisps aren’t con­sid­ered pure func­tional lan­guages. But many pro­gram­mers haven’t been ex­posed to this id­iom, and thus tend to un­der­rate its ben­e­fits. I know I was in that category.

    Func­tional pro­gram­ming doesn’t mean pro­gram­ming with func­tions. Every­body does that. Func­tional pro­gram­ming refers to a stricter style where func­tions re­ceive cer­tain data as in­put, process only that data, and re­turn a re­sult. In func­tional pro­gram­ming, func­tions avoid two habits com­mon in other lan­guages: data mu­ta­tion (= chang­ing data in-place rather than re­turn­ing a value) and re­ly­ing on state (= ex­tra con­text that’s not pro­vided as in­put, for in­stance global variables).

    “Wait—I love state and data mu­ta­tion. Why would you take them away?” Be­cause they’re false friends. They con­tra­dict the es­sen­tial con­cept of a func­tion, which is to en­cap­su­late data and al­go­rithms. When a func­tion re­lies on state or mu­ta­tion, it’s op­er­at­ing out­side those bound­aries. You ei­ther take on an in­creas­ing house­keep­ing bur­den to keep track of how func­tions af­fect each other, or watch the pro­gram sink into a swamp of mys­te­ri­ous, com­pli­cated bugs.

    Pro­gram­ming in a func­tional style takes more ef­fort at the out­set. But it en­cour­ages you to struc­ture the pro­gram in a clean, com­part­men­tal­ized way. This pays off im­me­di­ately in pro­grams that are eas­ier to test and de­bug. It’s also more likely to lead to reusable com­po­nents, since func­tions are truly independent.

    This bite-the-bul­let as­pect of func­tional pro­gram­ming is an­other rea­son why you can get “more done, faster” with a Lisp. The dif­fer­ence be­tween pro­to­type and pro­duc­tion code of­ten ends up be­ing small, be­cause you don’t take as many short­cuts at the start. The pro­gram grows and evolves more smoothly be­cause it’s easy to change one part with­out caus­ing rip­ple ef­fects elsewhere.

  4. Li­braries & doc­u­men­ta­tion. [Racket] This might not look like a com­pet­i­tive dif­fer­en­tia­tor—doesn’t every pro­gram­ming lan­guage have li­braries & documentation?

    Yes, but prob­a­bly not like this. As a con­se­quence of be­ing used in re­search set­tings for many years—Racket’s core de­vel­op­ment team is mostly CS pro­fes­sors—Racket’s li­braries & docs are more like a trans­mis­sion from a highly evolved alien intelligence.

    You get the es­sen­tials, of course: web server, JSON, XML, draw­ing, for­eign-func­tion in­ter­face, and so on. Then you no­tice pack­ages you maybe didn’t ex­pect: GUI ap­pli­ca­tion frame­work, math plot­ting, pack­age-dis­tri­bu­tion sys­tem, unit tester. Be­yond that, your face starts to melt a lit­tle bit: se­man­tics en­gi­neer­ing? Fu­tures visualizer?

    I won’t pre­tend to know what all this shit does. A lot of it is over my head. But I like that. Each week I use Racket, I end up ex­plor­ing a new part of the li­brary, and learn­ing some­thing new. As op­posed to other lan­guages that seem to kill brain cells on con­tact (= pretty much any­thing named *Script, I find).

    This learn­ing is only pos­si­ble be­cause of Racket’s truly out­stand­ing doc­u­men­ta­tion. It’s vast, thor­ough, pre­cise, and ap­proach­able. See for yourself.

  5. Dr­Racket. [Racket] Yes, I know how to use a com­mand line. But Racket in­cludes a cross-plat­form graph­i­cal IDE called Dr­Racket that’s pretty great. Dr­Racket lets you edit, run, and de­bug Racket source files (or any other lan­guage based on Racket—see item #9 on this list.)

    No, it doesn’t have the Ginsu-level search-and-re­place fa­cil­i­ties of some­thing like Sub­lime Text. But it does have help­ful edit­ing fea­tures op­ti­mized for Racket code (for in­stance, you can right-click on a sym­bol name and re­name it through­out the file, or jump from a func­tion to its documentation).

    More­over, the com­mand line within Dr­Racket doesn’t just show plain text—it can show stacked frac­tions, draw­ings, math plots, and other un­ex­pected guests. If your com­mand line does all that, by all means keep us­ing it.

  6. X-ex­pres­sions. [Lisps] This choice is some­what bi­ased by my work with Racket, which mostly in­volves doc­u­ment pro­cess­ing and type­set­ting. But re­lated top­ics arise in most web pro­gram­ming. An X-ex­pres­sion is a spe­cial na­tive data struc­ture that Lisps use to rep­re­sent HTML and other XML-ish data.

    Well, not “spe­cial” in a Lispy sense—keep­ing with the usual pol­icy, an X-ex­pres­sion is just an­other list—but spe­cial in the sense that other pro­gram­ming lan­guages don’t have it. Usu­ally your choice is to rep­re­sent HTML ei­ther as a string or as a full XML tree. A string is wrong be­cause it doesn’t cap­ture the struc­ture of the HTML, as de­fined by its tags and at­trib­utes. An XML tree shows this struc­ture, but con­ceals the se­quen­tial na­ture of the data el­e­ments, and is un­wieldy to work with.

    An X-ex­pres­sion ends up be­ing an ideal hy­brid be­tween a string and a tree. More­over, be­cause it’s just an­other list-based ex­pres­sion in the lan­guage, you have a lot of op­tions for pro­cess­ing it. Trans­lat­ing an X-ex­pres­sion to or from a text rep­re­sen­ta­tion us­ing an­gle brack­ets is triv­ial and fast. (De­tails.)

    Given the close kin­ship be­tween XML-ish data struc­tures and Lisp lan­guages, I have no ex­pla­na­tion why, dur­ing the in­ter­net era, they’ve not been paired more of­ten. They’re like peanut but­ter and jelly.

  7. Scrib­ble. [Racket] Pollen wouldn’t have been pos­si­ble with­out Scrib­ble, so for me, this has been the stone-cold killer fea­ture of Racket. But that won’t be true for every­one, so I’m mov­ing it down on the list.

    Scrib­ble is a di­alect of Racket that in­verts the or­di­nary re­la­tion­ship of plain text and code: rather than em­bed­ding text strings within source, a Scrib­ble doc­u­ment con­sists of code ex­pres­sions em­bed­ded within plain text.

    “So it’s like an HTML tem­plate lan­guage.” Yes, in the sense that a tem­plate lan­guage al­lows code to be em­bed­ded in text. But also no, be­cause a tem­plate lan­guage is usu­ally a pid­gin ver­sion of a real pro­gram­ming lan­guage. Scrib­ble, by con­trast, lets you in­voke any Racket code sim­ply by adding a com­mand char­ac­ter to the front. In keep­ing with the theme al­ready es­tab­lished, this ap­proach is both sim­pler (be­cause there’s al­most noth­ing new to learn) and more pow­er­ful (be­cause you can in­voke any­thing in Racket).

    In its com­bi­na­tion of text and code, Scrib­ble has more kin­ship with La­TeX. While it doesn’t have the type­set­ting fa­cil­i­ties of La­TeX, the pro­gram­ming fa­cil­i­ties are much better.

  8. Macros. [Racket] Also known in Racket as syn­tax trans­for­ma­tions. Se­ri­ous Rack­e­teers some­times pre­fer that term be­cause a Racket macro can be far more so­phis­ti­cated than the usual Com­mon Lisp macro.

    A macro in Com­mon Lisp is a func­tion that runs at com­pile-time, ac­cept­ing sym­bols as in­put and in­ject­ing them into a tem­plate to pro­duce new code. Syn­tax trans­for­ma­tions in Racket, on the other hand, rely on the con­cept of hy­giene and can of­fer Com­mon Lisp-style macros, but also more elab­o­rate syn­tax rearrangements.

    But for­get that—what’s in it for you? As a pro­gram­mer, you end up get­ting two bites at the ap­ple every time you run a file: Racket runs the syn­tax trans­for­ma­tions (which al­ter the source code), and then the source code itself.

    Un­like some­thing like the C pre­proces­sor, which is ba­si­cally a sep­a­rate mini-lan­guage, Racket syn­tax trans­for­ma­tions are them­selves Racket func­tions that give you ac­cess to every­thing in Racket. Like lists and ex­pres­sions, syn­tax trans­for­ma­tions add an­other layer of ex­pres­sive possibilities.

  9. Cre­ate new pro­gram­ming lan­guages. [Racket] When I first read that Racket could be used to cre­ate new lan­guages, I had two thoughts—are they se­ri­ous? and would I really want to do that? The an­swers were yes and oh hell yes.

    Be­tween ex­pres­sions, lists, and syn­tax trans­for­ma­tions, Racket gives you a huge amount of se­man­tic flex­i­bil­ity. But on top of that, it also adds syn­tac­tic flex­i­b­lity, in that you can de­fine a reader that con­verts sur­face syn­tax into stan­dard Racket.

    You can use this fa­cil­ity to make spe­cial­ized di­alects of Racket. Or im­ple­ment ear­lier lan­guages. Or cre­ate en­tirely new lan­guages with their own rules. You can use any of these lan­guages within Dr­Racket to code new projects. (These spe­cial lan­guages are some­times called do­main-spe­cific lan­guages, or DSLs.) Scrib­ble is a DSL based on Racket; Pollen is a set of DSLs based on Scribble.

    If you’re like most pro­gram­mers, you’ve never had a tool for mak­ing a new lan­guage, so you’ve not con­sid­ered it a re­al­is­tic ap­proach to a prob­lem. And maybe you’ll never use it. But when you do, it is awe­some, in both the new and old senses of that word.

  10. Op­por­tu­ni­ties to par­tic­i­pate. [Racket] In the­ory, open-source soft­ware projects cre­ate the op­por­tu­nity for groups of de­vel­op­ers to join to­gether and make bet­ter things in col­lab­o­ra­tion than they could separately.

    In prac­tice, I’ve found that open-source projects sort into a bi­modal dis­tri­bu­tion: over here, the un­der­doc­u­mented solo projects that sput­ter along fit­fully (if at all); over there, the ma­ture, pop­u­lar projects that can be in­tim­i­dat­ing for new contributors.

    As an open-source project, Racket is po­si­tioned at a happy medium. The core de­vel­op­ment team has been work­ing to­gether for years, and the com­mits re­main fast & fu­ri­ous. But they’re friendly sci­en­tists, not Shire-dwelling ego­tists, and re­main re­cep­tive to im­prove­ments across the whole sys­tem. If you have a bet­ter idea, they’ll lis­ten; if you code it up to their stan­dards and make a pull re­quest, they’ll take it.

    [2021 up­date: I no longer con­tribute to Racket due to abuse & bul­ly­ing by the project lead­er­ship. Every­one in the broader Racket com­mu­nity, how­ever, has al­ways been help­ful and kind.]

The point of this list has been to tell you about the pos­i­tives. That doesn’t mean there aren’t neg­a­tives. The small pool of Racket pro­gram­mers means that when you hit a pot­hole, it’s pos­si­ble no one’s ever seen your prob­lem (= the in­verse of Li­nus’s Law). If I wanted to hire a Racket pro­gram­mer, the op­tions would be few.

Still, why shouldn’t I be en­thu­si­as­tic? What I’ve been able to ac­com­plish so far with Racket has been tremen­dously use­ful, ed­u­ca­tional, and fun—the most fun I’ve had in 25+ years of programming.

If you think I sound like a fan­boy or cult mem­ber, I can live with that. But those are peo­ple whose en­thu­si­asm is dis­pro­por­tion­ate to re­al­ity. Here, I’ve tried to stay out of the clouds (and the weeds) and ex­plain the con­crete, prac­ti­cal fea­tures that have made Racket such a plea­sure in my own work.

As al­ways, your mileage may vary. But if I per­suade a few peo­ple to down­load Racket and try it, I’ll be happy. In fact, if you try it and don’t like it, I in­vite you to con­tact me, be­cause I’m al­ways cu­ri­ous to hear dis­sent­ing opinions.

I will end by tak­ing on the big kahuna—

I won’t claim I’ve reached the top of the moun­tain. But I can tell you what the view looks like so far.

There’s a sense in which Lisp and its de­scen­dants are more than pro­gram­ming lan­guages. They’re tools in the broader in­tel­lec­tual in­quiry into the the­ory of com­pu­ta­tion. Lisp’s in­ven­tor, John Mc­Carthy, orig­i­nally con­sid­ered Lisp a “way of de­scrib­ing com­putable func­tions much neater than the Tur­ing ma­chines”, adapt­ing the no­ta­tion of lambda cal­cu­lus to do so. Racket, like­wise, has grown out of sci­en­tific re­search and exploration.

The the­ory of com­pu­ta­tion is just one of many great sci­en­tific dis­cov­er­ies in the last 100 years. But I don’t get to use quan­tum me­chan­ics or rel­a­tiv­ity or DNA se­quenc­ing in my daily work. When I’m pro­gram­ming, how­ever, I’m us­ing computation.

Racket, as a Lisp di­alect, has many prac­ti­cal ben­e­fits. But it also opens a win­dow onto this vast the­o­ret­i­cal world that un­der­lies every­thing we can do with pro­grams. I’m not a brainiac com­puter sci­en­tist. But some days, through that win­dow, I can start to see a bit of what they see—some math, some sci­ence, a lot of truth, and more than a lit­tle beauty and mystery.

Paul Gra­ham calls Lisp a “se­cret weapon”. I would clar­ify: Lisp it­self isn’t the se­cret weapon. Rather, you are—be­cause a Lisp lan­guage of­fers you the chance to dis­cover your po­ten­tial as a pro­gram­mer and a thinker, and thereby raise your ex­pec­ta­tions for what you can accomplish.

If that’s not a step to­ward en­light­en­ment, I don’t know what is.

The afore­men­tioned Struc­ture and In­ter­pre­ta­tion of Com­puter Pro­grams de­serves every com­pli­ment it gets. It’s mind-bend­ingly great, and ac­ces­si­ble to any­one with a mild cu­rios­ity about soft­ware. By us­ing Scheme to il­lus­trate meta-top­ics about pro­grams, it im­pliedly makes a great case for Lisps.

Like­wise, Pe­ter Norvig’s Par­a­digms of Ar­ti­fi­cial In­tel­li­gence Pro­gram­ming is not in­tended as a gen­eral in­tro­duc­tion to Lisp, but it ends up do­ing that job well, by show­ing how so­phis­ti­cated pro­grams can arise from small con­struc­tions of Lisp code.

As I’ve al­ready men­tioned, Racket’s doc­u­men­ta­tion is con­sis­tently ex­cel­lent. Sim­ply read­ing through The Racket Guide and try­ing some ex­am­ples is rewarding.

I ex­plain more about why Racket was es­sen­tial for Pollen in the Pollen documentation.

If you want to try Racket, you can down­load the cur­rent sta­ble ver­sion (easy), a nightly build (easy), or com­pile it from source (slightly daunt­ing the first time but then easy).

—Matthew But­t­er­ick
20 Aug 2014

by the way
  • At Rack­et­Con in Sep­tem­ber 2014, I gave a short talk about Pollen, ty­pog­ra­phy, and dig­i­tal book­mak­ing. Here’s the video.

undock move Heliotrope Equity Valkyrie Century Supra Concourse Triplicate buy font close