Populair Zijn

Mei 2001

(Dit artikel werd geschreven als een soort businessplan voor een nieuwe taal. Het mist dus (omdat het vanzelfsprekend is) het belangrijkste kenmerk van een goede programmeertaal: zeer krachtige abstracties.)

Een vriend van mij vertelde ooit aan een vooraanstaande expert op het gebied van besturingssystemen dat hij een echt goede programmeertaal wilde ontwerpen. De expert vertelde hem dat het tijdverspilling zou zijn, dat programmeertalen niet populair of impopulair worden op basis van hun verdiensten, en dus zou niemand zijn taal gebruiken, hoe goed die ook was. Althans, dat was wat er met de taal was gebeurd die hij had ontworpen.

Wat maakt een taal populair? Verdienen populaire talen hun populariteit? Is het de moeite waard om een goede programmeertaal te definiëren? Hoe zou je dat doen?

Ik denk dat de antwoorden op deze vragen te vinden zijn door naar hackers te kijken en te leren wat zij willen. Programmeertalen zijn voor hackers, en een programmeertaal is goed als programmeertaal (in plaats van bijvoorbeeld een oefening in denotatieve semantiek of compilerontwerp) als en slechts als hackers het leuk vinden.

1 De Mechanica van Populariteit

Het is zeker waar dat de meeste mensen programmeertalen niet simpelweg op basis van hun verdiensten kiezen. De meeste programmeurs krijgen te horen welke taal ze moeten gebruiken door iemand anders. En toch denk ik dat het effect van dergelijke externe factoren op de populariteit van programmeertalen niet zo groot is als soms wordt gedacht. Ik denk dat een groter probleem is dat het idee van een hacker van een goede programmeertaal niet hetzelfde is als dat van de meeste taalontwerpers.

Van de twee is de mening van de hacker de enige die ertoe doet. Programmeertalen zijn geen stellingen. Het zijn gereedschappen, ontworpen voor mensen, en ze moeten net zo goed ontworpen zijn om menselijke sterktes en zwaktes te passen als schoenen voor menselijke voeten. Als een schoen knelt als je hem aantrekt, is het een slechte schoen, hoe elegant hij ook mag zijn als een stuk beeldhouwwerk.

Het kan zijn dat de meerderheid van de programmeurs een goede taal niet van een slechte kan onderscheiden. Maar dat geldt voor elk ander gereedschap. Het betekent niet dat het tijdverspilling is om te proberen een goede taal te ontwerpen. Expert hackers kunnen een goede taal herkennen als ze die zien, en ze zullen hem gebruiken. Expert hackers zijn weliswaar een kleine minderheid, maar die kleine minderheid schrijft alle goede software, en hun invloed is zodanig dat de rest van de programmeurs de neiging zal hebben om welke taal ze ook gebruiken. Vaak is het niet slechts invloed, maar bevel: vaak zijn de expert hackers juist degenen die, als hun bazen of faculteitsadviseurs, de andere programmeurs vertellen welke taal ze moeten gebruiken.

De mening van expert hackers is niet de enige kracht die de relatieve populariteit van programmeertalen bepaalt — legacy software (Cobol) en hype (Ada, Java) spelen ook een rol — maar ik denk dat het de krachtigste kracht is op de lange termijn. Gegeven een initiële kritische massa en voldoende tijd, wordt een programmeertaal waarschijnlijk ongeveer zo populair als hij verdient te zijn. En populariteit scheidt goede talen verder van slechte, want feedback van echte gebruikers leidt altijd tot verbeteringen. Kijk hoeveel elke populaire taal gedurende zijn leven is veranderd. Perl en Fortran zijn extreme gevallen, maar zelfs Lisp is veel veranderd. Lisp 1.5 had bijvoorbeeld geen macro's; deze zijn later geëvolueerd, nadat hackers aan MIT een paar jaar Lisp hadden gebruikt om echte programma's te schrijven.[1]

Dus of een taal goed moet zijn om populair te zijn, ik denk dat een taal populair moet zijn om goed te zijn. En hij moet populair blijven om goed te blijven. De stand van de techniek in programmeertalen staat niet stil. En toch zijn de Lisp-varianten die we vandaag hebben nog steeds grotendeels wat ze hadden in MIT in het midden van de jaren '80, omdat dat de laatste keer was dat Lisp een voldoende grote en veeleisende gebruikersbasis had.

Natuurlijk moeten hackers van een taal weten voordat ze die kunnen gebruiken. Hoe horen ze ervan? Van andere hackers. Maar er moet een initiële groep hackers zijn die de taal gebruikt, zodat anderen er überhaupt van kunnen horen. Ik vraag me af hoe groot deze groep moet zijn; hoeveel gebruikers maken een kritische massa? Uit mijn hoofd zou ik zeggen twintig. Als een taal twintig afzonderlijke gebruikers had, wat betekent dat twintig gebruikers die uit eigen beweging besloten hem te gebruiken, zou ik hem als echt beschouwen.

Daar komen kan niet makkelijk zijn. Het zou me niet verbazen als het moeilijker is om van nul naar twintig te gaan dan van twintig naar duizend. De beste manier om die eerste twintig gebruikers te krijgen, is waarschijnlijk door een paard van Troje te gebruiken: mensen een applicatie geven die ze willen, die toevallig in de nieuwe taal is geschreven.

2 Externe Factoren

Laten we beginnen met het erkennen van één externe factor die de populariteit van een programmeertaal beïnvloedt. Om populair te worden, moet een programmeertaal de scriptingtaal zijn van een populair systeem. Fortran en Cobol waren de scriptingtalen van vroege IBM mainframes. C was de scriptingtaal van Unix, en later ook Perl. Tcl is de scriptingtaal van Tk. Java en Javascript zijn bedoeld om de scriptingtalen van webbrowsers te zijn.

Lisp is geen massaal populaire taal omdat het niet de scriptingtaal is van een massaal populair systeem. Welke populariteit het behoudt, dateert uit de jaren '60 en '70, toen het de scriptingtaal van MIT was. Veel van de grote programmeurs van die tijd waren op een gegeven moment verbonden aan MIT. En begin jaren '70, vóór C, was het dialect van Lisp van MIT, MacLisp genaamd, een van de weinige programmeertalen die een serieuze hacker wilde gebruiken.

Vandaag de dag is Lisp de scriptingtaal van twee middelmatig populaire systemen, Emacs en Autocad, en om die reden vermoed ik dat de meeste Lisp-programmering die vandaag de dag wordt gedaan, wordt gedaan in Emacs Lisp of AutoLisp.

Programmeertalen bestaan niet in isolatie. Hacking is een transitief werkwoord — hackers zijn meestal ergens mee bezig — en in de praktijk worden talen beoordeeld ten opzichte van waar ze voor gebruikt worden. Dus als je een populaire taal wilt ontwerpen, moet je ofwel meer dan een taal leveren, ofwel je taal ontwerpen om de scriptingtaal van een bestaand systeem te vervangen.

Common Lisp is deels impopulair omdat het een weeskind is. Het kwam oorspronkelijk wel met een systeem om mee te hacken: de Lisp Machine. Maar Lisp Machines (samen met parallelle computers) werden verpletterd door de toenemende kracht van algemene processors in de jaren '80. Common Lisp was misschien populair gebleven als het een goede scriptingtaal voor Unix was geweest. Het is, helaas, een afschuwelijk slechte.

Eén manier om deze situatie te beschrijven, is te zeggen dat een taal niet op zijn eigen merites wordt beoordeeld. Een andere kijk is dat een programmeertaal eigenlijk geen programmeertaal is, tenzij het ook de scriptingtaal van iets is. Dit lijkt alleen oneerlijk als het als een verrassing komt. Ik denk dat het niet oneerlijker is dan te verwachten dat een programmeertaal bijvoorbeeld een implementatie heeft. Het is gewoon een deel van wat een programmeertaal is.

Een programmeertaal heeft natuurlijk wel een goede implementatie nodig, en deze moet gratis zijn. Bedrijven betalen voor software, maar individuele hackers niet, en het zijn de hackers die je moet aantrekken.

Een taal heeft ook een boek nodig. Het boek moet dun, goed geschreven en vol met goede voorbeelden zijn. K&R is hier het ideaal. Op dit moment zou ik bijna zeggen dat een taal een boek moet hebben dat door O'Reilly is uitgegeven. Dat wordt de test om ertoe te doen voor hackers.

Er moet ook online documentatie zijn. Sterker nog, het boek kan beginnen als online documentatie. Maar ik denk niet dat fysieke boeken al achterhaald zijn. Hun formaat is handig, en de de facto censuur door uitgevers is een nuttig, zij het onvolmaakt, filter. Boekwinkels zijn een van de belangrijkste plekken om over nieuwe talen te leren.

3 Beknoptheid

Gegeven dat je de drie dingen kunt leveren die elke taal nodig heeft — een gratis implementatie, een boek en iets om mee te hacken — hoe maak je dan een taal die hackers leuk vinden?

Eén ding dat hackers leuk vinden, is beknoptheid. Hackers zijn lui, op dezelfde manier als wiskundigen en modernistische architecten lui zijn: ze haten alles wat overbodig is. Het zou niet ver van de waarheid zijn om te zeggen dat een hacker die op het punt staat een programma te schrijven, onbewust beslist welke taal hij gaat gebruiken op basis van het totale aantal tekens dat hij moet typen. Als dit niet precies is hoe hackers denken, doet een taalontwerper er goed aan om te doen alsof het wel zo is.

Het is een vergissing om te proberen de gebruiker te vertroetelen met langdradige uitdrukkingen die bedoeld zijn om op Engels te lijken. Cobol is berucht om deze fout. Een hacker zou het schrijven van

voeg x toe aan y met z als resultaat

in plaats van

z = x+y

als iets tussen een belediging van zijn intelligentie en een zonde tegen God beschouwen.

Er is soms gezegd dat Lisp first en rest zou moeten gebruiken in plaats van car en cdr, omdat het programma's gemakkelijker leesbaar zou maken. Misschien de eerste paar uur. Maar een hacker kan snel genoeg leren dat car het eerste element van een lijst betekent en cdr de rest. Het gebruik van first en rest betekent 50% meer typwerk. En ze hebben ook verschillende lengtes, wat betekent dat de argumenten niet zullen uitlijnen wanneer ze worden aangeroepen, zoals car en cdr vaak doen, op opeenvolgende regels. Ik heb gemerkt dat hoe code op de pagina uitlijnt, veel uitmaakt. Ik kan Lisp-code nauwelijks lezen wanneer deze in een lettertype met variabele breedte is gezet, en vrienden zeggen dat dit ook geldt voor andere talen.

Beknoptheid is een plek waar sterk getypeerde talen verliezen. Alle andere dingen gelijk, niemand wil een programma beginnen met een reeks declaraties. Alles wat impliciet kan zijn, moet dat ook zijn.

De individuele tokens moeten ook kort zijn. Perl en Common Lisp nemen tegenovergestelde polen in op deze vraag. Perl-programma's kunnen bijna cryptisch dicht zijn, terwijl de namen van ingebouwde Common Lisp-operatoren komisch lang zijn. De ontwerpers van Common Lisp verwachtten waarschijnlijk dat gebruikers tekstverwerkers zouden hebben die deze lange namen voor hen zouden typen. Maar de kosten van een lange naam zijn niet alleen de kosten van het typen ervan. Er zijn ook de kosten van het lezen ervan, en de kosten van de ruimte die het op je scherm inneemt.

4 Hackbaarheid

Er is één ding belangrijker dan beknoptheid voor een hacker: de mogelijkheid om te doen wat je wilt. In de geschiedenis van programmeertalen is verrassend veel moeite gestoken in het voorkomen dat programmeurs dingen doen die als ongepast worden beschouwd. Dit is een gevaarlijk pretentieuze plan. Hoe kan de taalontwerper weten wat de programmeur moet doen? Ik denk dat taalontwerpers er beter aan zouden doen hun doelgebruiker te beschouwen als een genie dat dingen moet doen die zij nooit hebben voorzien, in plaats van een prutser die tegen zichzelf beschermd moet worden. De prutser zal zichzelf sowieso in de voet schieten. Je kunt hem redden van het verwijzen naar variabelen in een ander pakket, maar je kunt hem niet redden van het schrijven van een slecht ontworpen programma om het verkeerde probleem op te lossen, en er eeuwig over doen.

Goede programmeurs willen vaak gevaarlijke en onsmakelijke dingen doen. Met onsmakelijk bedoel ik dingen die voorbijgaan aan welke semantische façade de taal ook probeert te presenteren: het verkrijgen van de interne representatie van een hoog-niveau abstractie, bijvoorbeeld. Hackers houden van hacken, en hacken betekent dingen van binnenuit bekijken en de oorspronkelijke ontwerper in twijfel trekken.

Laat je in twijfel trekken. Wanneer je een gereedschap maakt, gebruiken mensen het op manieren die je niet hebt bedoeld, en dit geldt in het bijzonder voor een zeer gearticuleerd gereedschap als een programmeertaal. Veel hackers zullen je semantische model willen aanpassen op een manier die je nooit hebt bedacht. Ik zeg, laat ze; geef de programmeur toegang tot zoveel mogelijk interne zaken als je kunt zonder runtime-systemen zoals de garbage collector in gevaar te brengen.

In Common Lisp heb ik vaak door de velden van een structuur willen itereren — om bijvoorbeeld verwijzingen naar een verwijderd object te verwijderen, of velden te vinden die niet zijn geïnitialiseerd. Ik weet dat de structuren onderliggend gewoon vectoren zijn. En toch kan ik geen algemene functie schrijven die ik op elke structuur kan aanroepen. Ik kan de velden alleen op naam benaderen, omdat dat is wat een structuur zou moeten betekenen.

Een hacker wil misschien maar één of twee keer in een groot programma het beoogde model ondermijnen. Maar wat een verschil maakt het om dat te kunnen. En het kan meer zijn dan alleen het oplossen van een probleem. Er is hier ook een soort plezier. Hackers delen het geheime genoegen van de chirurg bij het rondprikken in de grove ingewanden, het geheime genoegen van de tiener bij het uitknijpen van puistjes.[2] Voor jongens, althans, zijn bepaalde soorten gruwelen fascinerend. Maxim magazine publiceert een jaarlijks fotoboek, met een mix van pin-ups en gruwelijke ongelukken. Ze kennen hun publiek.

Historisch gezien is Lisp goed geweest in het laten doen wat hackers willen. De politieke correctheid van Common Lisp is een aberratie. Vroege Lisp-varianten lieten je overal bij komen. Veel van die geest is gelukkig behouden gebleven in macro's. Wat een prachtig iets, om willekeurige transformaties op de broncode te kunnen maken.

Klassieke macro's zijn een echt hacker-gereedschap — eenvoudig, krachtig en gevaarlijk. Het is zo gemakkelijk te begrijpen wat ze doen: je roept een functie aan op de argumenten van de macro, en wat die retourneert, wordt op de plaats van de macro-aanroep ingevoegd. Hygiënische macro's belichamen het tegenovergestelde principe. Ze proberen je te beschermen tegen het begrijpen van wat ze doen. Ik heb nog nooit gehoord dat hygiënische macro's in één zin worden uitgelegd. En ze zijn een klassiek voorbeeld van de gevaren van het bepalen wat programmeurs mogen willen. Hygiënische macro's zijn bedoeld om me te beschermen tegen variabele vangst, onder andere, maar variabele vangst is precies wat ik wil in sommige macro's.

Een echt goede taal moet zowel schoon als vies zijn: schoon ontworpen, met een kleine kern van goed begrepen en zeer orthogonale operatoren, maar vies in de zin dat het hackers hun gang laat gaan. C is zo. De vroege Lisp-varianten ook. Een echte hackerstaal zal altijd een enigszins louche karakter hebben.

Een goede programmeertaal moet functies hebben die het soort mensen dat de uitdrukking "software engineering" gebruikt, met afkeuring doet hoofdschudden. Aan het andere uiteinde van het continuüm staan talen als Ada en Pascal, modellen van fatsoen die goed zijn om te onderwijzen en verder niet veel.

5 Wegwerpprogramma's

Om aantrekkelijk te zijn voor hackers, moet een taal goed zijn voor het schrijven van de soorten programma's die zij willen schrijven. En dat betekent, misschien verrassend genoeg, dat hij goed moet zijn voor het schrijven van wegwerpprogramma's.

Een wegwerpprogramma is een programma dat je snel schrijft voor een beperkte taak: een programma om een systeembeheerstaak te automatiseren, testgegevens te genereren voor een simulatie, of gegevens van het ene formaat naar het andere te converteren. Het verrassende aan wegwerpprogramma's is dat ze, net als de "tijdelijke" gebouwen die op zoveel Amerikaanse universiteiten tijdens de Tweede Wereldoorlog werden gebouwd, vaak niet worden weggegooid. Velen evolueren tot echte programma's, met echte functies en echte gebruikers.

Ik heb de neiging dat de beste grote programma's zo beginnen, in plaats van vanaf het begin groot te worden ontworpen, zoals de Hoover Dam. Het is angstaanjagend om iets groots vanaf nul te bouwen. Wanneer mensen een te groot project aannemen, worden ze overweldigd. Het project loopt vast, of het resultaat is steriel en houterig: een winkelcentrum in plaats van een echt stadscentrum, Brasilia in plaats van Rome, Ada in plaats van C.

Een andere manier om een groot programma te krijgen, is door te beginnen met een wegwerpprogramma en het te blijven verbeteren. Deze aanpak is minder ontmoedigend, en het ontwerp van het programma profiteert van evolutie. Ik denk dat, als men zou kijken, dit de manier zou blijken te zijn waarop de meeste grote programma's werden ontwikkeld. En degenen die op deze manier evolueerden, worden waarschijnlijk nog steeds geschreven in de taal waarin ze oorspronkelijk werden geschreven, omdat het zeldzaam is dat een programma wordt geporteerd, behalve om politieke redenen. En dus, paradoxaal genoeg, als je een taal wilt maken die voor grote systemen wordt gebruikt, moet je hem goed maken voor het schrijven van wegwerpprogramma's, want daar komen grote systemen vandaan.

Perl is een treffend voorbeeld van dit idee. Het was niet alleen ontworpen voor het schrijven van wegwerpprogramma's, maar was zelf grotendeels een wegwerpprogramma. Perl begon als een verzameling hulpprogramma's voor het genereren van rapporten, en evolueerde pas tot een programmeertaal naarmate de wegwerpprogramma's die mensen erin schreven groter werden. Pas met Perl 5 (en zelfs toen) was de taal geschikt voor het schrijven van serieuze programma's, en toch was hij al enorm populair.

Wat maakt een taal goed voor wegwerpprogramma's? Om te beginnen moet hij direct beschikbaar zijn. Een wegwerpprogramma is iets dat je verwacht in een uur te schrijven. Dus de taal moet waarschijnlijk al geïnstalleerd zijn op de computer die je gebruikt. Het kan niet iets zijn dat je moet installeren voordat je het kunt gebruiken. Het moet er zijn. C was er omdat het bij het besturingssysteem kwam. Perl was er omdat het oorspronkelijk een hulpmiddel was voor systeembeheerders, en de jouwe had het al geïnstalleerd.

Beschikbaar zijn betekent echter meer dan geïnstalleerd zijn. Een interactieve taal, met een command-line interface, is toegankelijker dan een taal die je apart moet compileren en uitvoeren. Een populaire programmeertaal moet interactief zijn en snel opstarten.

Een ander ding dat je wilt in een wegwerpprogramma is beknoptheid. Beknoptheid is altijd aantrekkelijk voor hackers, en nooit meer dan in een programma dat ze verwachten in een uur af te ronden.

6 Bibliotheken

Het ultieme in beknoptheid is natuurlijk om het programma al geschreven te hebben, en het alleen maar aan te roepen. En dit brengt ons bij wat ik denk dat een steeds belangrijker kenmerk van programmeertalen zal zijn: bibliotheekfuncties. Perl wint omdat het grote bibliotheken heeft voor het manipuleren van strings. Dit type bibliotheekfuncties is vooral belangrijk voor wegwerpprogramma's, die vaak oorspronkelijk worden geschreven voor het converteren of extraheren van gegevens. Veel Perl-programma's beginnen waarschijnlijk als slechts een paar bibliotheekaanroepen die aan elkaar zijn gekoppeld.

Ik denk dat veel van de vooruitgang die de komende vijftig jaar in programmeertalen zal plaatsvinden, te maken zal hebben met bibliotheekfuncties. Ik denk dat toekomstige programmeertalen bibliotheken zullen hebben die net zo zorgvuldig zijn ontworpen als de kern van de taal. Taalontwerp zal niet gaan over of je je taal sterk of zwak getypeerd, objectgeoriënteerd, functioneel, of wat dan ook maakt, maar over hoe je geweldige bibliotheken ontwerpt. Het soort taalontwerpers dat graag nadenkt over hoe je typesystemen ontwerpt, zal hier misschien van huiveren. Het is bijna als het schrijven van applicaties! Jammer. Talen zijn voor programmeurs, en bibliotheken zijn wat programmeurs nodig hebben.

Het is moeilijk om goede bibliotheken te ontwerpen. Het is niet simpelweg een kwestie van veel code schrijven. Zodra de bibliotheken te groot worden, kan het soms langer duren om de functie te vinden die je nodig hebt dan om de code zelf te schrijven. Bibliotheken moeten worden ontworpen met behulp van een kleine set orthogonale operatoren, net als de kern van de taal. Het moet mogelijk zijn voor de programmeur om te raden welke bibliotheekaanroep zal doen wat hij nodig heeft.

Bibliotheken zijn een punt waarop Common Lisp tekortschiet. Er zijn slechts rudimentaire bibliotheken voor het manipuleren van strings, en bijna geen voor het communiceren met het besturingssysteem. Om historische redenen probeert Common Lisp te doen alsof het OS niet bestaat. En omdat je niet met het OS kunt praten, is het onwaarschijnlijk dat je een serieus programma kunt schrijven met alleen de ingebouwde operatoren in Common Lisp. Je moet ook gebruik maken van implementatie-specifieke hacks, en in de praktijk geven deze je meestal niet alles wat je wilt. Hackers zouden veel meer waardering hebben voor Lisp als Common Lisp krachtige stringbibliotheken en goede OS-ondersteuning had.

7 Syntaxis

Zou een taal met de syntaxis van Lisp, of preciezer, het gebrek aan syntaxis, ooit populair kunnen worden? Ik ken het antwoord op deze vraag niet. Ik denk wel dat syntaxis niet de belangrijkste reden is waarom Lisp momenteel niet populair is. Common Lisp heeft ergere problemen dan onbekende syntaxis. Ik ken verschillende programmeurs die comfortabel zijn met prefix-notatie en toch standaard Perl gebruiken, omdat het krachtige stringbibliotheken heeft en met het OS kan praten.

Er zijn twee mogelijke problemen met prefix-notatie: dat het onbekend is voor programmeurs, en dat het niet dicht genoeg is. De conventionele wijsheid in de Lisp-wereld is dat het eerste probleem het echte is. Ik ben daar niet zo zeker van. Ja, prefix-notatie maakt gewone programmeurs bang. Maar ik denk niet dat de meningen van gewone programmeurs ertoe doen. Talen worden populair of impopulair op basis van wat expert hackers ervan denken, en ik denk dat expert hackers wel met prefix-notatie om zouden kunnen gaan. Perl-syntaxis kan behoorlijk onbegrijpelijk zijn, maar dat heeft de populariteit van Perl niet in de weg gestaan. Sterker nog, het kan hebben bijgedragen aan een Perl-cultus.

Een serieuzer probleem is de diffusiteit van prefix-notatie. Voor expert hackers is dat echt een probleem. Niemand wil (aref a x y) schrijven als ze a[x,y] zouden kunnen schrijven.

In dit specifieke geval is er een manier om het probleem te omzeilen. Als we datastructuren behandelen als functies op indices, zouden we in plaats daarvan (a x y) kunnen schrijven, wat nog korter is dan de Perl-vorm. Vergelijkbare trucs kunnen andere soorten expressies verkorten.

We kunnen veel haakjes elimineren (of optioneel maken) door de inspringing significant te maken. Dat is hoe programmeurs code toch lezen: wanneer de inspringing het ene zegt en de scheidingstekens het andere, volgen we de inspringing. Het significant maken van inspringing zou deze veelvoorkomende bron van bugs elimineren en ook programma's korter maken.

Soms is infix-syntaxis gemakkelijker te lezen. Dit geldt met name voor wiskundige uitdrukkingen. Ik gebruik Lisp mijn hele programmeerleven en ik vind prefix-wiskundige uitdrukkingen nog steeds niet natuurlijk. En toch is het handig, vooral als je code genereert, om operatoren te hebben die een willekeurig aantal argumenten nemen. Dus als we infix-syntaxis hebben, zou deze waarschijnlijk moeten worden geïmplementeerd als een soort read-macro.

Ik denk niet dat we religieus tegen het introduceren van syntaxis in Lisp moeten zijn, zolang het op een goed begrepen manier wordt vertaald naar onderliggende s-expressies. Er is al veel syntaxis in Lisp. Het is niet noodzakelijk slecht om meer te introduceren, zolang niemand gedwongen wordt het te gebruiken. In Common Lisp zijn sommige scheidingstekens gereserveerd voor de taal, wat suggereert dat ten minste enkele van de ontwerpers van plan waren om meer syntaxis in de toekomst te hebben.

Een van de meest schromelijk on-Lisp-achtige stukken syntaxis in Common Lisp komt voor in format strings; format is op zichzelf al een taal, en die taal is geen Lisp. Als er een plan was om meer syntaxis in Lisp te introduceren, zouden format-specificaties daarin kunnen worden opgenomen. Het zou goed zijn als macro's format-specificaties konden genereren op dezelfde manier als ze elk ander soort code genereren.

Een vooraanstaande Lisp-hacker vertelde me dat zijn exemplaar van CLTL openslaat bij de sectie format. Dat van mij ook. Dit geeft waarschijnlijk ruimte voor verbetering. Het kan ook betekenen dat programma's veel I/O doen.

8 Efficiëntie

Een goede taal moet, zoals iedereen weet, snelle code genereren. Maar in de praktijk denk ik niet dat snelle code voornamelijk voortkomt uit dingen die je doet in het ontwerp van de taal. Zoals Knuth lang geleden al aangaf, snelheid doet er alleen toe in bepaalde kritieke knelpunten. En zoals veel programmeurs sindsdien hebben waargenomen, vergist men zich heel vaak in waar deze knelpunten zich bevinden.

Dus, in de praktijk, de manier om snelle code te krijgen, is door een zeer goede profiler te hebben, in plaats van bijvoorbeeld de taal sterk getypeerd te maken. Je hoeft niet het type van elk argument in elke aanroep in het programma te kennen. Je moet wel de types van argumenten in de knelpunten kunnen declareren. En nog meer, je moet kunnen achterhalen waar de knelpunten zich bevinden.

Een klacht die mensen over Lisp hebben gehad, is dat het moeilijk is om te zeggen wat duur is. Dit kan waar zijn. Het kan ook onvermijdelijk zijn, als je een zeer abstracte taal wilt hebben. En in ieder geval denk ik dat een goede profiling een heel eind zou helpen om het probleem op te lossen: je zou snel leren wat duur is.

Een deel van het probleem hier is sociaal. Taalontwerpers schrijven graag snelle compilers. Zo meten ze hun vaardigheid. Ze beschouwen de profiler als een add-on, op zijn best. Maar in de praktijk kan een goede profiler meer doen om de snelheid van daadwerkelijke programma's die in de taal zijn geschreven te verbeteren dan een compiler die snelle code genereert. Hier zijn taalontwerpers opnieuw enigszins losgezongen van hun gebruikers. Ze doen echt goed werk bij het oplossen van een enigszins verkeerd probleem.

Het zou een goed idee kunnen zijn om een actieve profiler te hebben — om prestatiegegevens naar de programmeur te pushen in plaats van te wachten tot hij erom vraagt. De editor zou bijvoorbeeld knelpunten in rood kunnen weergeven wanneer de programmeur de broncode bewerkt. Een andere aanpak zou zijn om op de een of andere manier weer te geven wat er gebeurt in draaiende programma's. Dit zou een bijzonder grote winst zijn in server-gebaseerde applicaties, waar je veel draaiende programma's hebt om naar te kijken. Een actieve profiler zou grafisch kunnen weergeven wat er in het geheugen gebeurt terwijl een programma draait, of zelfs geluiden maken die vertellen wat er gebeurt.

Geluid is een goede indicator van problemen. Op een plek waar ik werkte, hadden we een groot bord met wijzerplaten die lieten zien wat er met onze webservers gebeurde. De wijzers werden bewogen door kleine servomotoren die een zacht geluid maakten als ze draaiden. Ik kon het bord vanaf mijn bureau niet zien, maar ik merkte dat ik onmiddellijk aan het geluid kon horen wanneer er een probleem was met een server.

Het zou zelfs mogelijk kunnen zijn om een profiler te schrijven die inefficiënte algoritmen automatisch detecteert. Het zou me niet verbazen als bepaalde patronen van geheugentoegang zekere tekenen van slechte algoritmen zouden blijken te zijn. Als er een klein mannetje rondliep in de computer die onze programma's uitvoerde, zou hij waarschijnlijk een net zo lang en klaaglijk verhaal te vertellen hebben over zijn baan als een werknemer van de federale overheid. Ik heb vaak het gevoel dat ik de processor op veel dwaalsporen stuur, maar ik heb nooit een goede manier gehad om te kijken wat hij doet.

Een aantal Lisp-varianten compileert nu naar byte code, die vervolgens door een interpreter wordt uitgevoerd. Dit wordt meestal gedaan om de implementatie gemakkelijker te porteren, maar het zou een nuttige taal functie kunnen zijn. Het zou een goed idee kunnen zijn om de byte code een officieel onderdeel van de taal te maken, en programmeurs toe te staan inline byte code te gebruiken in knelpunten. Dan zouden dergelijke optimalisaties ook draagbaar zijn.

De aard van snelheid, zoals waargenomen door de eindgebruiker, kan veranderen. Met de opkomst van server-gebaseerde applicaties, kunnen steeds meer programma's I/O-gebonden blijken te zijn. Het zal de moeite waard zijn om I/O snel te maken. De taal kan helpen met eenvoudige maatregelen zoals eenvoudige, snelle, opgemaakte uitvoerfuncties, en ook met diepgaande structurele veranderingen zoals caching en persistente objecten.

Gebruikers zijn geïnteresseerd in responstijd. Maar een ander soort efficiëntie zal steeds belangrijker worden: het aantal gelijktijdige gebruikers dat je per processor kunt ondersteunen. Veel van de interessante applicaties die in de nabije toekomst zullen worden geschreven, zullen server-gebaseerd zijn, en het aantal gebruikers per server is de kritieke vraag voor iedereen die dergelijke applicaties host. In de kapitaalkosten van een bedrijf dat een server-gebaseerde applicatie aanbiedt, is dit de deler.

Jarenlang was efficiëntie in de meeste eindgebruikersapplicaties niet erg belangrijk. Ontwikkelaars konden ervan uitgaan dat elke gebruiker een steeds krachtigere processor op zijn bureau zou hebben. En volgens Parkinson's Law heeft software zich uitgebreid om de beschikbare middelen te gebruiken. Dat zal veranderen met server-gebaseerde applicaties. In die wereld zullen de hardware en software samen worden geleverd. Voor bedrijven die server-gebaseerde applicaties aanbieden, zal het een heel groot verschil maken voor de bottom line hoeveel gebruikers ze per server kunnen ondersteunen.

In sommige applicaties zal de processor de beperkende factor zijn, en de uitvoeringssnelheid zal het belangrijkste zijn om te optimaliseren. Maar vaak zal het geheugen de limiet zijn; het aantal gelijktijdige gebruikers zal worden bepaald door de hoeveelheid geheugen die je nodig hebt voor de gegevens van elke gebruiker. De taal kan hier ook helpen. Goede ondersteuning voor threads zal alle gebruikers in staat stellen om een enkele heap te delen. Het kan ook helpen om persistente objecten en/of taalondersteuning voor lazy loading te hebben.

9 Tijd

Het laatste ingrediënt dat een populaire taal nodig heeft, is tijd. Niemand wil programma's schrijven in een taal die mogelijk verdwijnt, zoals zoveel programmeertalen doen. Dus de meeste hackers zullen de neiging hebben om te wachten tot een taal een paar jaar bestaat voordat ze er zelfs maar aan denken om hem te gebruiken.

Uitvinders van prachtige nieuwe dingen zijn vaak verrast dit te ontdekken, maar je hebt tijd nodig om enige boodschap over te brengen aan mensen. Een vriend van mij doet zelden iets de eerste keer dat iemand hem iets vraagt. Hij weet dat mensen soms om dingen vragen die ze uiteindelijk niet willen. Om zijn tijd niet te verspillen, wacht hij tot de derde of vierde keer dat hij iets gevraagd wordt te doen; tegen die tijd is degene die hem vraagt waarschijnlijk behoorlijk geïrriteerd, maar dan willen ze waarschijnlijk wel echt wat ze vragen.

De meeste mensen hebben geleerd om een soortgelijk filter toe te passen op nieuwe dingen waarover ze horen. Ze beginnen pas aandacht te besteden als ze tien keer over iets hebben gehoord. Ze zijn volkomen gerechtvaardigd: de meerderheid van de hete nieuwe wat-dan-ook blijkt tijdverspilling te zijn, en verdwijnt uiteindelijk. Door het leren van VRML uit te stellen, heb ik het helemaal niet hoeven te leren.

Dus iedereen die iets nieuws uitvindt, moet verwachten dat hij zijn boodschap jarenlang blijft herhalen voordat mensen het gaan begrijpen. Wij schreven wat, voor zover ik weet, de eerste webserver-gebaseerde applicatie was, en het kostte ons jaren om mensen duidelijk te maken dat het niet gedownload hoefde te worden. Ze waren niet dom. Ze hadden ons gewoon genegeerd.

Het goede nieuws is dat simpele herhaling het probleem oplost. Het enige wat je hoeft te doen, is je verhaal blijven vertellen, en uiteindelijk zullen mensen gaan luisteren. Het is niet wanneer mensen merken dat je er bent dat ze aandacht besteden; het is wanneer ze merken dat je er nog steeds bent.

Het is maar goed dat het meestal even duurt om momentum te krijgen. De meeste technologieën evolueren aanzienlijk, zelfs nadat ze voor het eerst zijn gelanceerd — programmeertalen in het bijzonder. Niets is beter voor een nieuwe technologie dan een paar jaar lang alleen gebruikt te worden door een klein aantal early adopters. Early adopters zijn veeleisend en veeleisend, en spoelen snel alle resterende gebreken in je technologie weg. Als je maar een paar gebruikers hebt, kun je met ze allemaal in nauw contact zijn. En early adopters zijn vergevingsgezind als je je systeem verbetert, zelfs als dit enige breuk veroorzaakt.

Er zijn twee manieren waarop nieuwe technologie wordt geïntroduceerd: de organische groeimethode en de big bang-methode. De organische groeimethode wordt geïllustreerd door de klassieke, ondergefinancierde garage-startup. Een paar jongens, die in obscuriteit werken, ontwikkelen nieuwe technologie. Ze lanceren het zonder marketing en hebben aanvankelijk slechts een paar (fanatiek toegewijde) gebruikers. Ze blijven de technologie verbeteren, en ondertussen groeit hun gebruikersbestand via mond-tot-mondreclame. Voordat ze het weten, zijn ze groot.

De andere aanpak, de big bang-methode, wordt geïllustreerd door de door VC gesteunde, zwaar gemarkete startup. Ze haasten zich om een product te ontwikkelen, lanceren het met grote publiciteit, en hebben onmiddellijk (hopen ze) een grote gebruikersbasis.

Over het algemeen benijden de garagejongens de big bang-jongens. De big bang-jongens zijn soepel en zelfverzekerd en worden gerespecteerd door de VC's. Ze kunnen zich het beste van alles veroorloven, en de PR-campagne rond de lancering heeft als bijkomend effect dat ze beroemdheden worden. De organische groei-jongens, die in hun garage zitten, voelen zich arm en onbemind. En toch denk ik dat ze zich vaak ten onrechte beklagen. Organische groei lijkt betere technologie en rijkere oprichters op te leveren dan de big bang-methode. Als je kijkt naar de dominante technologieën van vandaag, zul je merken dat de meeste ervan organisch zijn gegroeid.

Dit patroon geldt niet alleen voor bedrijven. Je ziet het ook in gesponsord onderzoek. Multics en Common Lisp waren big bang-projecten, en Unix en MacLisp waren organische groei-projecten.

10 Herontwerp

"Het beste schrijven is herschrijven", schreef E. B. White. Elke goede schrijver weet dit, en het geldt ook voor software. Het belangrijkste onderdeel van ontwerp is herontwerp. Programmeertalen, vooral, worden niet genoeg herontworpen.

Om goede software te schrijven, moet je tegelijkertijd twee tegengestelde ideeën in je hoofd houden. Je hebt het naïeve geloof van de jonge hacker in zijn capaciteiten nodig, en tegelijkertijd het scepticisme van de veteraan. Je moet met de ene helft van je hersenen kunnen denken hoe moeilijk kan het zijn? terwijl je met de andere helft denkt het zal nooit werken.

De truc is om te beseffen dat er geen echte tegenstrijdigheid is. Je wilt optimistisch en sceptisch zijn over twee verschillende dingen. Je moet optimistisch zijn over de mogelijkheid om het probleem op te lossen, maar sceptisch over de waarde van welke oplossing je tot nu toe hebt.

Mensen die goed werk doen, denken vaak dat wat ze ook aan het doen zijn, niet goed is. Anderen zien wat ze hebben gedaan en zijn vol verwondering, maar de maker is vol zorgen. Dit patroon is geen toeval: het is de zorg die het werk goed heeft gemaakt.

Als je hoop en zorg in evenwicht kunt houden, zullen ze een project vooruit drijven op dezelfde manier als je twee benen een fiets vooruit drijven. In de eerste fase van de tweewielige innovatiemotor werk je koortsachtig aan een probleem, geïnspireerd door je vertrouwen dat je het kunt oplossen. In de tweede fase kijk je naar wat je hebt gedaan in het koude licht van de ochtend, en zie je al zijn gebreken heel duidelijk. Maar zolang je kritische geest je hoop niet overtreft, zul je naar je toegegeven onvolledige systeem kunnen kijken en denken, hoe moeilijk kan het zijn om de rest te doen?, en zo de cyclus voortzetten.

Het is lastig om de twee krachten in evenwicht te houden. Bij jonge hackers domineert optimisme. Ze produceren iets, zijn ervan overtuigd dat het geweldig is, en verbeteren het nooit. Bij oude hackers domineert scepticisme, en ze durven ambitieuze projecten niet eens aan te gaan.

Alles wat je kunt doen om de herontwerpcyclus gaande te houden, is goed. Proza kan keer op keer worden herschreven totdat je er tevreden mee bent. Maar software wordt over het algemeen niet genoeg herontworpen. Proza heeft lezers, maar software heeft gebruikers. Als een schrijver een essay herschrijft, zullen mensen die de oude versie lazen waarschijnlijk niet klagen dat hun gedachten zijn verbroken door een nieuw geïntroduceerde incompatibiliteit.

Gebruikers zijn een tweesnijdend zwaard. Ze kunnen je helpen je taal te verbeteren, maar ze kunnen je ook ontmoedigen om hem te verbeteren. Kies je gebruikers dus zorgvuldig, en wees langzaam met het vergroten van hun aantal. Gebruikers hebben is als optimalisatie: de wijze koers is om het uit te stellen. Ook, als algemene regel, kun je op elk gegeven moment meer veranderen dan je denkt. Verandering introduceren is als het aftrekken van een pleister: de pijn is een herinnering bijna zodra je hem voelt.

Iedereen weet dat het geen goed idee is om een taal te laten ontwerpen door een commissie. Commissies leveren slecht ontwerp op. Maar ik denk dat het grootste gevaar van commissies is dat ze herontwerp in de weg staan. Het is zoveel werk om veranderingen door te voeren dat niemand zich eraan wil storen. Wat een commissie ook beslist, blijft zo, zelfs als de meeste leden het niet leuk vinden.

Zelfs een commissie van twee staat herontwerp in de weg. Dit gebeurt met name bij de interfaces tussen stukken software die door twee verschillende mensen zijn geschreven. Om de interface te veranderen, moeten beiden tegelijkertijd instemmen met de wijziging. En dus veranderen interfaces meestal helemaal niet, wat een probleem is omdat ze meestal een van de meest ad hoc onderdelen van elk systeem zijn.

Een oplossing hiervoor zou kunnen zijn om systemen zo te ontwerpen dat interfaces horizontaal in plaats van verticaal zijn — zodat modules altijd verticaal gestapelde lagen van abstractie zijn. Dan zal de interface meestal eigendom zijn van een van hen. Het onderste van de twee niveaus zal ofwel een taal zijn waarin het bovenste is geschreven, in welk geval het onderste niveau de interface zal bezitten, of het zal een slaaf zijn, in welk geval de interface kan worden gedicteerd door het bovenste niveau.

11 Lisp

Wat dit alles impliceert, is dat er hoop is voor een nieuwe Lisp. Er is hoop voor elke taal die hackers biedt wat ze willen, inclusief Lisp. Ik denk dat we een fout hebben gemaakt door te denken dat hackers worden afgeschrikt door de vreemdheid van Lisp. Deze troostrijke illusie heeft ons misschien belet het echte probleem met Lisp, of althans Common Lisp, te zien, namelijk dat het slecht is voor het doen wat hackers willen doen. Een hackerstaal heeft krachtige bibliotheken en iets om mee te hacken nodig. Common Lisp heeft geen van beide. Een hackerstaal is beknopt en hackbaar. Common Lisp is dat niet.

Het goede nieuws is dat het niet Lisp is dat slecht is, maar Common Lisp. Als we een nieuwe Lisp kunnen ontwikkelen die een echte hackerstaal is, denk ik dat hackers die zullen gebruiken. Ze zullen elke taal gebruiken die het werk doet. Het enige wat we hoeven te doen, is ervoor zorgen dat deze nieuwe Lisp een belangrijke taak beter uitvoert dan andere talen.

De geschiedenis biedt enige aanmoediging. Na verloop van tijd hebben opeenvolgende nieuwe programmeertalen steeds meer functies uit Lisp overgenomen. Er is niet veel meer te kopiëren voordat de taal die je hebt gemaakt Lisp is. De nieuwste populaire taal, Python, is een verwaterde Lisp met infix-syntaxis en geen macro's. Een nieuwe Lisp zou een natuurlijke stap in deze progressie zijn.

Ik denk soms dat het een goede marketingtruc zou zijn om het een verbeterde versie van Python te noemen. Dat klinkt hipper dan Lisp. Voor veel mensen is Lisp een trage AI-taal met veel haakjes. Fritz Kunze's officiële biografie vermijdt zorgvuldig het vermelden van het L-woord. Maar mijn gok is dat we er niet bang voor moeten zijn om de nieuwe Lisp Lisp te noemen. Lisp heeft nog steeds veel latente respect onder de allerbeste hackers — degenen die 6.001 hebben gevolgd en het begrepen, bijvoorbeeld. En dat zijn de gebruikers die je moet winnen.

In "How to Become a Hacker" beschrijft Eric Raymond Lisp als iets als Latijn of Grieks — een taal die je als intellectuele oefening zou moeten leren, ook al zul je hem niet echt gebruiken:

Lisp is de moeite waard om te leren voor de diepgaande verhelderende ervaring die je zult hebben wanneer je het eindelijk begrijpt; die ervaring zal je de rest van je dagen een betere programmeur maken, zelfs als je Lisp zelf nooit veel gebruikt.

Als ik Lisp niet kende, zou ik hierdoor vragen gaan stellen. Een taal die me een betere programmeur zou maken, als het al iets betekent, betekent een taal die beter zou zijn voor programmeren. En dat is inderdaad de implicatie van wat Eric zegt.

Zolang dat idee nog rondzweeft, denk ik dat hackers ontvankelijk genoeg zullen zijn voor een nieuwe Lisp, zelfs als die Lisp heet. Maar deze Lisp moet een hackerstaal zijn, zoals de klassieke Lisp-varianten uit de jaren '70. Hij moet beknopt, eenvoudig en hackbaar zijn. En hij moet krachtige bibliotheken hebben voor wat hackers nu willen doen.

Op het gebied van bibliotheken denk ik dat er ruimte is om talen als Perl en Python te overtreffen in hun eigen spel. Veel van de nieuwe applicaties die de komende jaren geschreven moeten worden, zullen server-gebaseerde applicaties zijn. Er is geen reden waarom een nieuwe Lisp geen stringbibliotheken zou moeten hebben die net zo goed zijn als die van Perl, en als deze nieuwe Lisp ook krachtige bibliotheken voor server-gebaseerde applicaties zou hebben, zou hij erg populair kunnen worden. Echte hackers zullen hun neus niet ophalen voor een nieuw gereedschap dat hen in staat stelt moeilijke problemen op te lossen met een paar bibliotheekaanroepen. Vergeet niet, hackers zijn lui.

Het zou een nog grotere winst kunnen zijn om ondersteuning op het niveau van de kern van de taal te hebben voor server-gebaseerde applicaties. Bijvoorbeeld, expliciete ondersteuning voor programma's met meerdere gebruikers, of gegevensbezit op het niveau van type tags.

Server-gebaseerde applicaties geven ons ook het antwoord op de vraag waarvoor deze nieuwe Lisp gebruikt zal worden om mee te hacken. Het zou niet schaden om Lisp beter te maken als scriptingtaal voor Unix. (Het zou moeilijk zijn om het slechter te maken.) Maar ik denk dat er gebieden zijn waar bestaande talen gemakkelijker te verslaan zijn. Ik denk dat het beter zou zijn om het model van Tcl te volgen, en Lisp te leveren samen met een compleet systeem voor het ondersteunen van server-gebaseerde applicaties. Lisp is een natuurlijke keuze voor server-gebaseerde applicaties. Lexicale closures bieden een manier om het effect van subroutines te krijgen wanneer de UI slechts een reeks webpagina's is. S-expressies passen mooi op HTML, en macro's zijn goed in het genereren ervan. Er zijn betere tools nodig voor het schrijven van server-gebaseerde applicaties, en er is een nieuwe Lisp nodig, en de twee zouden heel goed samenwerken.

12 De Droomtaal

Ter samenvatting, laten we proberen de droomtaal van de hacker te beschrijven. De droomtaal is mooi, schoon en beknopt. Hij heeft een interactieve toplevel die snel opstart. Je kunt programma's schrijven om veelvoorkomende problemen op te lossen met heel weinig code. Bijna alle code in elk programma dat je schrijft, is code die specifiek is voor jouw applicatie. Al het andere is voor jou gedaan.

De syntaxis van de taal is tot in het extreme beknopt. Je hoeft nooit een onnodig teken te typen, of zelfs de Shift-toets veel te gebruiken.

Met grote abstracties kun je de eerste versie van een programma heel snel schrijven. Later, als je wilt optimaliseren, is er een echt goede profiler die je vertelt waar je je aandacht op moet richten. Je kunt inner loops verblindend snel maken, zelfs inline byte code schrijven als je dat nodig hebt.

Er zijn veel goede voorbeelden om van te leren, en de taal is intuïtief genoeg dat je binnen een paar minuten kunt leren hoe je hem moet gebruiken aan de hand van voorbeelden. Je hoeft niet veel in de handleiding te kijken. De handleiding is dun, en bevat weinig waarschuwingen en kwalificaties.

De taal heeft een kleine kern, en krachtige, zeer orthogonale bibliotheken die net zo zorgvuldig zijn ontworpen als de kern van de taal. De bibliotheken werken allemaal goed samen; alles in de taal past bij elkaar als de onderdelen van een fijne camera. Niets is verouderd, of behouden voor compatibiliteit. De broncode van alle bibliotheken is direct beschikbaar. Het is gemakkelijk om te communiceren met het besturingssysteem en met applicaties die in andere talen zijn geschreven.

De taal is opgebouwd in lagen. De hogere abstracties zijn op een zeer transparante manier gebouwd uit lagere abstracties, die je kunt verkrijgen als je dat wilt.

Niets is voor jou verborgen dat niet absoluut noodzakelijk is. De taal biedt abstracties alleen als een manier om je werk te besparen, in plaats van als een manier om je te vertellen wat je moet doen. Sterker nog, de taal moedigt je aan om een gelijkwaardige deelnemer te zijn aan het ontwerp ervan. Je kunt alles eraan veranderen, zelfs de syntaxis, en alles wat je schrijft heeft, zoveel mogelijk, dezelfde status als wat vooraf is gedefinieerd.

Noten

[1] Macro's die heel dicht bij het moderne idee liggen, werden in 1964 voorgesteld door Timothy Hart, twee jaar na de release van Lisp 1.5. Wat aanvankelijk ontbrak, waren manieren om variabele vangst en meervoudige evaluatie te vermijden; de voorbeelden van Hart zijn aan beide onderhevig.

[2] In When the Air Hits Your Brain vertelt neurochirurg Frank Vertosick een gesprek waarin zijn hoofdresident, Gary, praat over het verschil tussen chirurgen en internisten ("vlooien"):

Gary en ik bestelden een grote pizza en vonden een open zitje. De chef stak een sigaret op. "Kijk naar die verdomde vlooien, die kwaken over een ziekte die ze maar één keer in hun leven zien. Dat is het probleem met vlooien, ze houden alleen van het bizarre spul. Ze haten hun brood-en-boter-gevallen. Dat is het verschil tussen ons en de verdomde vlooien. Zie je, wij houden van grote sappige lumbale hernia's, maar zij haten hypertensie...."

Het is moeilijk om een lumbale hernia als sappig te beschouwen (behalve letterlijk). En toch denk ik dat ik weet wat ze bedoelen. Ik heb vaak een sappige bug gehad om op te sporen. Iemand die geen programmeur is, zou het moeilijk vinden om te geloven dat er plezier kan zijn in een bug. Zeker, het is beter als alles gewoon werkt. Op de een of andere manier is dat zo. En toch is er onmiskenbaar een grimmige voldoening in het opsporen van bepaalde soorten bugs.