De Honderdjarige Taal
April 2003
(Deze essay is afgeleid van een keynote speech op PyCon 2003.)
Het is moeilijk te voorspellen hoe het leven over honderd jaar zal zijn. Er zijn maar een paar dingen die we met zekerheid kunnen zeggen. We weten dat iedereen vliegende auto's zal besturen, dat bestemmingsplannen zullen worden versoepeld om gebouwen van honderden verdiepingen toe te staan, dat het het grootste deel van de tijd donker zal zijn, en dat vrouwen allemaal getraind zullen zijn in vechtsporten. Hier wil ik inzoomen op één detail van dit beeld. Wat voor programmeertaal zullen ze gebruiken om de software te schrijven die die vliegende auto's bestuurt?
Dit is de moeite waard om over na te denken, niet zozeer omdat we deze talen daadwerkelijk zullen gebruiken, maar omdat we, als we geluk hebben, talen zullen gebruiken op het pad van dit punt naar dat.
Ik denk dat, net als soorten, talen evolutionaire bomen zullen vormen, met doodlopende takken die overal afsplitsen. We zien dit al gebeuren. Cobol, ondanks zijn vroegere populariteit, lijkt geen intellectuele nakomelingen te hebben. Het is een evolutionair doodlopende weg – een Neanderthalse taal.
Ik voorspel een soortgelijk lot voor Java. Mensen sturen me soms e-mails met de vraag: "Hoe kun je zeggen dat Java geen succesvolle taal zal blijken te zijn? Het is al een succesvolle taal." En ik geef toe dat het dat is, als je succes meet aan de ruimte die boeken erover innemen (vooral individuele boeken erover), of aan het aantal studenten dat gelooft dat ze het moeten leren om een baan te krijgen. Als ik zeg dat Java geen succesvolle taal zal blijken te zijn, bedoel ik iets specifieker: dat Java een evolutionair doodlopende weg zal blijken te zijn, net als Cobol.
Dit is slechts een gok. Ik kan het mis hebben. Mijn punt hier is niet om Java af te kraken, maar om de kwestie van evolutionaire bomen aan te snijden en mensen te laten vragen: waar op de boom bevindt taal X zich? De reden om deze vraag te stellen is niet alleen zodat onze geesten over honderd jaar kunnen zeggen: ik heb het je verteld. Het is omdat dicht bij de hoofdvertakkingen blijven een nuttige heuristiek is om talen te vinden die nu goed zijn om in te programmeren.
Op elk gegeven moment ben je waarschijnlijk het gelukkigst op de hoofdvertakkingen van een evolutionaire boom. Zelfs toen er nog volop Neanderthalers waren, moet het vreselijk zijn geweest om er een te zijn. De Cro-Magnons zouden je constant hebben lastiggevallen, je hebben geslagen en je eten hebben gestolen.
De reden dat ik wil weten hoe talen over honderd jaar zullen zijn, is zodat ik weet op welke tak van de boom ik nu moet wedden.
De evolutie van talen verschilt van de evolutie van soorten omdat takken kunnen samenkomen. De Fortran-tak lijkt bijvoorbeeld samen te smelten met de nakomelingen van Algol. In theorie is dit ook mogelijk voor soorten, maar het is waarschijnlijk niet groter dan een cel gebeurd.
Convergentie is waarschijnlijker voor talen, deels omdat de ruimte van mogelijkheden kleiner is, en deels omdat mutaties niet willekeurig zijn. Taalontwerpers nemen bewust ideeën uit andere talen op.
Het is vooral nuttig voor taalontwerpers om na te denken over waar de evolutie van programmeertalen waarschijnlijk naartoe zal leiden, omdat ze zich dienovereenkomstig kunnen richten. In dat geval wordt "op een hoofdvertakking blijven" meer dan een manier om een goede taal te kiezen. Het wordt een heuristiek voor het nemen van de juiste beslissingen over taalontwerp.
Elke programmeertaal kan in twee delen worden verdeeld: een reeks fundamentele operatoren die de rol van axioma's spelen, en de rest van de taal, die in principe kan worden geschreven in termen van deze fundamentele operatoren.
Ik denk dat de fundamentele operatoren de belangrijkste factor zijn voor het lange-termijn-overleven van een taal. De rest kun je veranderen. Het is als de regel dat je bij het kopen van een huis eerst moet kijken naar de locatie. Al het andere kun je later repareren, maar de locatie kun je niet repareren.
Ik denk dat het niet alleen belangrijk is dat de axioma's goed gekozen zijn, maar ook dat er weinig van zijn. Wiskundigen hebben dit altijd zo gevoeld over axioma's – hoe minder, hoe beter – en ik denk dat ze iets op het spoor zijn.
Op zijn minst moet het een nuttige oefening zijn om nauwkeurig naar de kern van een taal te kijken om te zien of er axioma's zijn die eruit gefilterd kunnen worden. Ik heb in mijn lange carrière als sloddervos ontdekt dat rommel rommel baart, en ik heb dit zowel in software als onder bedden en in de hoeken van kamers zien gebeuren.
Ik heb een vermoeden dat de hoofdvertakkingen van de evolutionaire boom door de talen lopen die de kleinste, schoonste kernen hebben. Hoe meer van een taal je in zichzelf kunt schrijven, hoe beter.
Natuurlijk doe ik een grote aanname door zelfs maar te vragen hoe programmeertalen over honderd jaar zullen zijn. Zullen we over honderd jaar nog steeds programma's schrijven? Zullen we computers niet gewoon vertellen wat we willen dat ze doen?
Er is tot nu toe niet veel vooruitgang geboekt op dat gebied. Mijn gok is dat mensen over honderd jaar computers nog steeds zullen vertellen wat ze moeten doen met programma's die we als zodanig zouden herkennen. Er kunnen taken zijn die we nu oplossen door programma's te schrijven en waarvoor je over honderd jaar geen programma's meer hoeft te schrijven, maar ik denk dat er nog steeds veel programmering zal zijn van het type dat we vandaag doen.
Het lijkt misschien pretentieus om te denken dat iemand kan voorspellen hoe technologie er over honderd jaar uit zal zien. Maar bedenk dat we al bijna vijftig jaar geschiedenis achter ons hebben. Vooruitkijken naar honderd jaar is een begrijpelijk idee als we bedenken hoe langzaam talen in het verleden zijn geëvolueerd.
Talen evolueren langzaam omdat het geen echte technologieën zijn. Talen zijn notatie. Een programma is een formele beschrijving van het probleem dat je een computer wilt laten oplossen. De evolutiesnelheid van programmeertalen is dus meer vergelijkbaar met de evolutiesnelheid van wiskundige notatie dan bijvoorbeeld transport of communicatie. Wiskundige notatie evolueert wel, maar niet met de gigantische sprongen die je in technologie ziet.
Waar computers over honderd jaar ook van gemaakt zijn, het lijkt veilig te voorspellen dat ze veel sneller zullen zijn dan nu. Als Moore's Law blijft doorgaan, zullen ze 74 quintiljoen (73.786.976.294.838.206.464) keer sneller zijn. Dat is moeilijk voor te stellen. En inderdaad, de meest waarschijnlijke voorspelling op het gebied van snelheid is dat Moore's Law zal stoppen met werken. Alles wat elke achttien maanden verdubbelt, lijkt uiteindelijk tegen een soort fundamentele limiet aan te lopen. Maar ik kan me zonder moeite voorstellen dat computers veel sneller zullen zijn. Zelfs als ze uiteindelijk slechts een schamele miljoen keer sneller zijn, zou dat de spelregels voor programmeertalen aanzienlijk moeten veranderen. Onder andere zal er meer ruimte zijn voor wat nu als trage talen zou worden beschouwd, namelijk talen die niet erg efficiënte code opleveren.
En toch zullen sommige toepassingen nog steeds snelheid eisen. Sommige problemen die we met computers willen oplossen, worden door computers zelf gecreëerd; de snelheid waarmee je videobeelden moet verwerken, hangt bijvoorbeeld af van de snelheid waarmee een andere computer ze kan genereren. En er is nog een klasse van problemen die inherent een onbeperkte capaciteit hebben om cycli op te slurpen: beeldrendering, cryptografie, simulaties.
Als sommige toepassingen steeds inefficiënter kunnen zijn terwijl andere alle snelheid blijven eisen die de hardware kan leveren, zullen snellere computers betekenen dat talen een steeds breder scala aan efficiënties moeten bestrijken. Dit zien we al gebeuren. Huidige implementaties van enkele populaire nieuwe talen zijn schokkend verspillend naar de maatstaven van voorgaande decennia.
Dit is niet alleen iets dat gebeurt met programmeertalen. Het is een algemene historische trend. Naarmate technologieën verbeteren, kan elke generatie dingen doen die de vorige generatie als verspillend zou hebben beschouwd. Mensen dertig jaar geleden zouden verbaasd zijn over hoe nonchalant we langeafstandstelefoongesprekken voeren. Mensen honderd jaar geleden zouden nog meer verbaasd zijn dat een pakketje ooit van Boston naar New York via Memphis zou reizen.
Ik kan je nu al vertellen wat er met al die extra cycli zal gebeuren die snellere hardware ons de komende honderd jaar zal opleveren. Ze zullen bijna allemaal worden verspild.
Ik leerde programmeren toen computerkracht schaars was. Ik kan me herinneren dat ik alle spaties uit mijn Basic-programma's haalde zodat ze in het geheugen van een 4K TRS-80 pasten. De gedachte aan al die verbijsterend inefficiënte software die cycli verbrandt om steeds hetzelfde te doen, lijkt me nogal weerzinwekkend. Maar ik denk dat mijn intuïties hier verkeerd zijn. Ik ben als iemand die arm is opgegroeid en geen geld kan uitgeven, zelfs niet voor iets belangrijks, zoals naar de dokter gaan.
Sommige soorten verspilling zijn echt walgelijk. SUV's bijvoorbeeld, zouden waarschijnlijk zelfs walgelijk zijn als ze draaiden op een brandstof die nooit opraakt en geen vervuiling genereert. SUV's zijn walgelijk omdat ze de oplossing zijn voor een walgelijk probleem. (Hoe je minivans mannelijker kunt laten lijken.) Maar niet alle verspilling is slecht. Nu we de infrastructuur hebben om het te ondersteunen, lijkt het tellen van de minuten van je langeafstandstelefoongesprekken kleingeestig. Als je de middelen hebt, is het eleganter om alle telefoongesprekken als één soort ding te beschouwen, ongeacht waar de andere persoon zich bevindt.
Er is goede verspilling en slechte verspilling. Ik ben geïnteresseerd in goede verspilling – het soort waarbij we door meer uit te geven, eenvoudigere ontwerpen kunnen krijgen. Hoe zullen we profiteren van de mogelijkheden om cycli te verspillen die we krijgen van nieuwe, snellere hardware?
Het verlangen naar snelheid is zo diep in ons geworteld, met onze nietige computers, dat het bewuste inspanning zal vergen om het te overwinnen. In taalontwerp moeten we bewust zoeken naar situaties waarin we efficiëntie kunnen inruilen voor zelfs de kleinste toename in gemak.
De meeste datastructuren bestaan vanwege snelheid. Veel talen hebben tegenwoordig bijvoorbeeld zowel strings als lijsten. Semantisch gezien zijn strings min of meer een subset van lijsten waarin de elementen karakters zijn. Dus waarom heb je een apart datatype nodig? Niet echt. Strings bestaan alleen voor efficiëntie. Maar het is flauw om de semantiek van de taal te vervuilen met hacks om programma's sneller te laten draaien. Het hebben van strings in een taal lijkt een geval van voortijdige optimalisatie.
Als we de kern van een taal beschouwen als een reeks axioma's, is het zeker weerzinwekkend om aanvullende axioma's te hebben die geen expressieve kracht toevoegen, puur omwille van efficiëntie. Efficiëntie is belangrijk, maar ik denk niet dat dat de juiste manier is om het te bereiken.
De juiste manier om dat probleem op te lossen, denk ik, is om de betekenis van een programma te scheiden van de implementatiedetails. In plaats van zowel lijsten als strings te hebben, heb je alleen lijsten, met een manier om de compiler optimalisatie-advies te geven dat het mogelijk maakt om strings als aaneengesloten bytes te rangschikken indien nodig.
Aangezien snelheid in de meeste van een programma niet uitmaakt, hoef je je normaal gesproken geen zorgen te maken over dit soort micromanagement. Dit zal steeds meer waar zijn naarmate computers sneller worden.
Minder zeggen over implementatie moet programma's ook flexibeler maken. Specificaties veranderen terwijl een programma wordt geschreven, en dit is niet alleen onvermijdelijk, maar wenselijk.
Het woord "essay" komt van het Franse werkwoord "essayer", wat "proberen" betekent. Een essay is, in de oorspronkelijke betekenis, iets dat je schrijft om iets uit te zoeken. Dit gebeurt ook in software. Ik denk dat sommige van de beste programma's essays waren, in de zin dat de auteurs bij aanvang niet precies wisten wat ze probeerden te schrijven.
Lisp-hackers weten al van de waarde van flexibiliteit met datastructuren. We schrijven meestal de eerste versie van een programma zo dat het alles met lijsten doet. Deze eerste versies kunnen zo schokkend inefficiënt zijn dat het bewuste inspanning vergt om niet na te denken over wat ze doen, net zoals het voor mij, althans, bewuste inspanning vereist om een steak niet te zien waar hij vandaan komt.
Wat programmeurs over honderd jaar het meest zullen zoeken, is een taal waarin je een ongelooflijk inefficiënte versie 1 van een programma met de minste moeite kunt samenstellen. Althans, zo zouden we het in de huidige termen beschrijven. Wat ze zullen zeggen, is dat ze een taal willen die gemakkelijk te programmeren is.
Inefficiënte software is niet vies. Wat vies is, is een taal die programmeurs onnodig werk laat doen. Het verspillen van programmeertijd is de ware inefficiëntie, niet het verspillen van machine-tijd. Dit zal steeds duidelijker worden naarmate computers sneller worden.
Ik denk dat het verwijderen van strings al iets is waar we over na zouden kunnen denken. We hebben het gedaan in Arc, en het lijkt een winst te zijn; sommige bewerkingen die onhandig te beschrijven zijn als reguliere expressies, kunnen gemakkelijk worden beschreven als recursieve functies.
Hoe ver zal deze afvlakking van datastructuren gaan? Ik kan mogelijkheden bedenken die zelfs mij schokken, met mijn gewetensvol verruimde geest. Zullen we bijvoorbeeld arrays afschaffen? Tenslotte zijn het slechts een subset van hashtabellen waarbij de sleutels vectoren van gehele getallen zijn. Zullen we hashtabellen zelf vervangen door lijsten?
Er zijn zelfs nog schokkendere vooruitzichten. De Lisp die McCarthy in 1960 beschreef, had bijvoorbeeld geen getallen. Logisch gezien hoef je geen aparte notie van getallen te hebben, omdat je ze als lijsten kunt weergeven: het gehele getal n kan worden weergegeven als een lijst van n elementen. Je kunt hiermee rekenen. Het is gewoon ondraaglijk inefficiënt.
Niemand heeft ooit voorgesteld om getallen in de praktijk als lijsten te implementeren. Sterker nog, McCarthy's paper uit 1960 was destijds niet bedoeld om geïmplementeerd te worden. Het was een theoretische oefening, een poging om een eleganter alternatief voor de Turing Machine te creëren. Toen iemand, onverwacht, dit paper nam en vertaalde naar een werkende Lisp-interpreter, werden getallen zeker niet als lijsten weergegeven; ze werden weergegeven in binair, zoals in elke andere taal.
Zou een programmeertaal zo ver kunnen gaan dat het getallen als fundamenteel datatype afschaft? Ik vraag dit niet zozeer als een serieuze vraag, maar als een manier om met de toekomst te spelen. Het is als het hypothetische geval van een onweerstaanbare kracht die een onbeweeglijk object ontmoet – hier, een onvoorstelbaar inefficiënte implementatie die onvoorstelbaar grote middelen ontmoet. Ik zie niet waarom niet. De toekomst is behoorlijk lang. Als er iets is dat we kunnen doen om het aantal axioma's in de kern van de taal te verminderen, lijkt dat de kant te zijn om op te wedden als t naar oneindig gaat. Als het idee over honderd jaar nog steeds ondraaglijk is, misschien is het dat over duizend jaar niet.
Om dit duidelijk te maken, ik stel niet voor dat alle numerieke berekeningen daadwerkelijk met lijsten zouden worden uitgevoerd. Ik stel voor dat de kern van de taal, voorafgaand aan aanvullende notaties over implementatie, zo wordt gedefinieerd. In de praktijk zou elk programma dat enige hoeveelheid wiskunde wilde doen, waarschijnlijk getallen in binair weergeven, maar dit zou een optimalisatie zijn, geen deel van de kernsemantiek van de taal.
Een andere manier om cycli te verbranden is door veel softwarelagen te hebben tussen de applicatie en de hardware. Dit is ook een trend die we al zien: veel recente talen worden gecompileerd naar byte code. Bill Woods vertelde me ooit dat, als vuistregel, elke laag interpretatie een factor 10 in snelheid kost. Deze extra kosten leveren flexibiliteit op.
De allereerste versie van Arc was een extreem geval van dit soort meerlaagse traagheid, met bijbehorende voordelen. Het was een klassieke "metacirculaire" interpreter geschreven bovenop Common Lisp, met een duidelijke familie-gelijkenis met de eval-functie gedefinieerd in McCarthy's originele Lisp-paper. Het geheel was slechts een paar honderd regels code, dus het was heel gemakkelijk te begrijpen en te veranderen. De Common Lisp die we gebruikten, CLisp, draait zelf bovenop een byte code interpreter. Dus hier hadden we twee niveaus van interpretatie, waarvan er één (de bovenste) schokkend inefficiënt was, en de taal was bruikbaar. Nauwelijks bruikbaar, geef ik toe, maar bruikbaar.
Software schrijven als meerdere lagen is zelfs binnen applicaties een krachtige techniek. Bottom-up programmeren betekent een programma schrijven als een reeks lagen, die elk dienen als een taal voor de laag erboven. Deze aanpak levert doorgaans kleinere, flexibelere programma's op. Het is ook de beste weg naar die heilige graal, herbruikbaarheid. Een taal is per definitie herbruikbaar. Hoe meer van je applicatie je in een taal voor dat type applicatie kunt onderbrengen, hoe meer van je software herbruikbaar zal zijn.
Op de een of andere manier raakte het idee van herbruikbaarheid in de jaren tachtig verbonden met objectgeoriënteerd programmeren, en geen enkele hoeveelheid bewijs van het tegendeel lijkt het te kunnen losmaken. Maar hoewel sommige objectgeoriënteerde software herbruikbaar is, is wat het herbruikbaar maakt de bottom-upheid, niet de objectgeoriënteerdheid. Beschouw bibliotheken: ze zijn herbruikbaar omdat ze taal zijn, of ze nu in een objectgeoriënteerde stijl zijn geschreven of niet.
Ik voorspel trouwens niet de ondergang van objectgeoriënteerd programmeren. Hoewel ik niet denk dat het veel te bieden heeft aan goede programmeurs, behalve in bepaalde gespecialiseerde domeinen, is het onweerstaanbaar voor grote organisaties. Objectgeoriënteerd programmeren biedt een duurzame manier om spaghetti-code te schrijven. Het laat je programma's accumuleren als een reeks patches. Grote organisaties ontwikkelen software altijd op deze manier, en ik verwacht dat dit over honderd jaar net zo waar zal zijn als vandaag.
Zolang we het over de toekomst hebben, kunnen we het beter hebben over parallelle berekeningen, want daar lijkt dit idee te leven. Dat wil zeggen, ongeacht wanneer je het hebt, parallelle berekeningen lijken iets te zijn dat in de toekomst gaat gebeuren.
Zal de toekomst het ooit inhalen? Mensen praten al minstens 20 jaar over parallelle berekeningen als iets dat op handen is, en het heeft de programmeerpraktijk tot nu toe niet veel beïnvloed. Of toch wel? Chipontwerpers moeten er al rekening mee houden, en dat geldt ook voor mensen die systeemsoftware schrijven op multi-CPU computers.
De echte vraag is, hoe ver omhoog in de abstractieladder zal parallellisme gaan? Zal het over honderd jaar zelfs applicatieprogrammeurs beïnvloeden? Of zal het iets zijn waar compiler-schrijvers over nadenken, maar dat meestal onzichtbaar is in de broncode van applicaties?
Eén ding dat waarschijnlijk lijkt, is dat de meeste mogelijkheden voor parallellisme zullen worden verspild. Dit is een speciaal geval van mijn algemenere voorspelling dat de meeste extra computerkracht die we krijgen, zal worden verspild. Ik verwacht dat, net als bij de verbazingwekkende snelheid van de onderliggende hardware, parallellisme iets zal zijn dat beschikbaar is als je er expliciet om vraagt, maar normaal gesproken niet wordt gebruikt. Dit impliceert dat het soort parallellisme dat we over honderd jaar hebben, behalve in speciale toepassingen, geen massaal parallellisme zal zijn. Ik verwacht dat het voor gewone programmeurs meer zal lijken op het kunnen afsplitsen van processen die allemaal parallel lopen.
En dit zal, net als het vragen om specifieke implementaties van datastructuren, iets zijn dat je vrij laat in de levensduur van een programma doet, wanneer je probeert het te optimaliseren. Versie 1 zal doorgaans alle voordelen van parallelle berekeningen negeren, net zoals het voordelen zal negeren die voortkomen uit specifieke representaties van gegevens.
Behalve in speciale soorten toepassingen, zal parallellisme de programma's die over honderd jaar worden geschreven niet doordringen. Het zou voortijdige optimalisatie zijn als dat wel het geval was.
Hoeveel programmeertalen zullen er over honderd jaar zijn? Er lijken de laatste tijd een enorm aantal nieuwe programmeertalen te zijn. Een deel van de reden is dat snellere hardware programmeurs in staat heeft gesteld om verschillende afwegingen te maken tussen snelheid en gemak, afhankelijk van de toepassing. Als dit een echte trend is, zal de hardware die we over honderd jaar hebben dit alleen maar vergroten.
En toch zullen er over honderd jaar misschien maar een paar veelgebruikte talen zijn. Een deel van de reden dat ik dit zeg, is optimisme: het lijkt erop dat, als je een heel goed werk had geleverd, je een taal zou kunnen maken die ideaal is voor het schrijven van een trage versie 1, en toch met het juiste optimalisatie-advies aan de compiler, ook zeer snelle code zou opleveren wanneer dat nodig is. Dus, omdat ik optimistisch ben, voorspel ik dat ondanks de enorme kloof die ze zullen hebben tussen acceptabele en maximale efficiëntie, programmeurs over honderd jaar talen zullen hebben die het grootste deel ervan kunnen overspannen.
Naarmate deze kloof groter wordt, zullen profilers steeds belangrijker worden. Er wordt nu weinig aandacht besteed aan profiling. Veel mensen lijken nog steeds te geloven dat de manier om snelle applicaties te krijgen is door compilers te schrijven die snelle code genereren. Naarmate de kloof tussen acceptabele en maximale prestaties groter wordt, zal het steeds duidelijker worden dat de manier om snelle applicaties te krijgen is door een goede gids van de ene naar de andere te hebben.
Als ik zeg dat er misschien maar een paar talen zullen zijn, bedoel ik geen domeinspecifieke "kleine talen". Ik denk dat dergelijke ingebedde talen een geweldig idee zijn, en ik verwacht dat ze zich zullen verspreiden. Maar ik verwacht dat ze als dunne genoeg skins zullen worden geschreven, zodat gebruikers de algemene taal eronder kunnen zien.
Wie zullen de talen van de toekomst ontwerpen? Een van de meest opwindende trends van de afgelopen tien jaar is de opkomst van open-source talen zoals Perl, Python en Ruby. Taalontwerp wordt overgenomen door hackers. De resultaten tot nu toe zijn rommelig, maar bemoedigend. Er zitten bijvoorbeeld verbazingwekkend nieuwe ideeën in Perl. Velen zijn verbazingwekkend slecht, maar dat geldt altijd voor ambitieuze inspanningen. In zijn huidige mutatiesnelheid, God weet in wat Perl over honderd jaar zou kunnen evolueren.
Het is niet waar dat wie niet kan, onderwijst (sommige van de beste hackers die ik ken zijn professoren), maar het is waar dat er veel dingen zijn die degenen die onderwijzen niet kunnen. Onderzoek legt beperkende kaste-restricties op. In elk academisch veld zijn er onderwerpen waarover het oké is om te werken en andere die dat niet zijn. Helaas is het onderscheid tussen acceptabele en verboden onderwerpen meestal gebaseerd op hoe intellectueel het werk klinkt wanneer het in onderzoeksartikelen wordt beschreven, in plaats van hoe belangrijk het is voor het verkrijgen van goede resultaten. Het extreme geval is waarschijnlijk literatuur; mensen die literatuur bestuderen, zeggen zelden iets dat van het minste nut zou zijn voor degenen die het produceren.
Hoewel de situatie beter is in de wetenschappen, is de overlap tussen het soort werk dat je mag doen en het soort werk dat goede talen oplevert, bedroevend klein. (Olin Shivers heeft hierover welsprekend gemopperd.) Types bijvoorbeeld, lijken een onuitputtelijke bron van onderzoeksartikelen te zijn, ondanks het feit dat statische typing echte macro's lijkt uit te sluiten – zonder welke, naar mijn mening, geen enkele taal de moeite waard is.
De trend gaat niet alleen naar talen die worden ontwikkeld als open-source projecten in plaats van "onderzoek", maar naar talen die worden ontworpen door de applicatieprogrammeurs die ze moeten gebruiken, in plaats van door compiler-schrijvers. Dit lijkt een goede trend en ik verwacht dat deze zal voortduren.
In tegenstelling tot de natuurkunde over honderd jaar, die bijna noodzakelijkerwijs onmogelijk te voorspellen is, denk ik dat het in principe mogelijk is om nu een taal te ontwerpen die gebruikers over honderd jaar zal aanspreken.
Een manier om een taal te ontwerpen is om gewoon het programma op te schrijven dat je zou willen kunnen schrijven, ongeacht of er een compiler is die het kan vertalen of hardware die het kan uitvoeren. Als je dit doet, kun je onbeperkte middelen aannemen. Het lijkt erop dat we onbeperkte middelen vandaag net zo goed kunnen bedenken als over honderd jaar.
Welk programma zou men willen schrijven? Wat het minste werk is. Behalve niet helemaal: wat het minste werk zou zijn als je ideeën over programmeren niet al beïnvloed waren door de talen die je momenteel gewend bent. Dergelijke invloed kan zo alomtegenwoordig zijn dat het grote inspanning vergt om het te overwinnen. Je zou denken dat het voor wezens die zo lui zijn als wij duidelijk zou zijn hoe je een programma met de minste inspanning uitdrukt. In feite zijn onze ideeën over wat mogelijk is zo beperkt door welke taal we ook denken, dat eenvoudigere formuleringen van programma's erg verrassend lijken. Het zijn dingen die je moet ontdekken, niet dingen waar je van nature in wegzakt.
Een nuttige truc hier is om de lengte van het programma te gebruiken als een benadering voor hoeveel werk het kost om te schrijven. Niet de lengte in tekens, natuurlijk, maar de lengte in verschillende syntactische elementen – in feite de grootte van de parse tree. Het is misschien niet helemaal waar dat het kortste programma het minste werk kost om te schrijven, maar het is dichtbij genoeg dat je beter kunt mikken op het solide doel van beknoptheid dan op het vage, nabijgelegen doel van minste werk. Dan wordt het algoritme voor taalontwerp: kijk naar een programma en vraag, is er een manier om dit te schrijven die korter is?
In de praktijk zal het schrijven van programma's in een imaginaire honderdjarige taal in wisselende mate werken, afhankelijk van hoe dicht je bij de kern bent. Sorteerroutines kun je nu schrijven. Maar het zou moeilijk zijn om nu te voorspellen welke soorten bibliotheken over honderd jaar nodig zouden zijn. Vermoedelijk zullen veel bibliotheken zijn voor domeinen die nog niet eens bestaan. Als SETI@home werkt, bijvoorbeeld, hebben we bibliotheken nodig voor communicatie met buitenaardse wezens. Tenzij ze natuurlijk voldoende geavanceerd zijn dat ze al in XML communiceren.
Aan de andere kant denk ik dat je de kern van de taal vandaag zou kunnen ontwerpen. Sterker nog, sommigen zouden kunnen beweren dat deze al grotendeels in 1958 was ontworpen.
Als de honderdjarige taal vandaag beschikbaar was, zouden we er dan in willen programmeren? Een manier om deze vraag te beantwoorden is door terug te kijken. Als de huidige programmeertalen beschikbaar waren geweest in 1960, zouden mensen ze dan hebben willen gebruiken?
In sommige opzichten is het antwoord nee. Talen van vandaag gaan uit van infrastructuur die in 1960 niet bestond. Een taal waarin bijvoorbeeld indentatie significant is, zoals Python, zou niet erg goed werken op printerterminals. Maar als we dergelijke problemen buiten beschouwing laten – ervan uitgaande dat programma's bijvoorbeeld allemaal op papier werden geschreven – zouden programmeurs uit de jaren zestig het leuk hebben gevonden om programma's te schrijven in de talen die we nu gebruiken?
Ik denk het wel. Sommigen van de minder fantasierijken, die artefacten van vroege talen in hun ideeën over wat een programma was, hadden ingebouwd, zouden er misschien moeite mee hebben gehad. (Hoe kun je gegevens manipuleren zonder pointer-arithmetiek te doen? Hoe kun je flowcharts implementeren zonder gotos?) Maar ik denk dat de slimste programmeurs er geen moeite mee zouden hebben gehad om het meeste uit de huidige talen te halen, als ze die hadden gehad.
Als we de honderdjarige taal nu hadden, zou het op zijn minst geweldige pseudocode zijn. Hoe zit het met het gebruik ervan om software te schrijven? Aangezien de honderdjarige taal voor sommige toepassingen snelle code moet genereren, zou het waarschijnlijk code kunnen genereren die efficiënt genoeg is om acceptabel te draaien op onze hardware. We moeten misschien meer optimalisatie-advies geven dan gebruikers over honderd jaar, maar het zou nog steeds een netto winst kunnen zijn.
Nu hebben we twee ideeën die, als je ze combineert, interessante mogelijkheden suggereren: (1) de honderdjarige taal zou in principe vandaag kunnen worden ontworpen, en (2) een dergelijke taal, als die zou bestaan, zou vandaag goed kunnen zijn om in te programmeren. Als je deze ideeën zo op een rijtje ziet, is het moeilijk om niet te denken: waarom probeer je de honderdjarige taal niet nu te schrijven?
Als je aan taalontwerp werkt, denk ik dat het goed is om zo'n doel te hebben en het bewust in gedachten te houden. Als je leert autorijden, is een van de principes die ze je leren om de auto niet uit te lijnen door de motorkap uit te lijnen met de strepen op de weg, maar door te richten op een punt in de verte. Zelfs als alles waar je om geeft is wat er in de volgende tien voet gebeurt, is dit het juiste antwoord. Ik denk dat we hetzelfde kunnen en moeten doen met programmeertalen.
Noten
Ik geloof dat Lisp Machine Lisp de eerste taal was die het principe belichaamde dat declaraties (behalve die van dynamische variabelen) slechts optimalisatie-advies waren, en de betekenis van een correct programma niet zouden veranderen. Common Lisp lijkt de eerste te zijn geweest die dit expliciet heeft vermeld.
Dank aan Trevor Blackwell, Robert Morris en Dan Giffin voor het lezen van concepten hiervan, en aan Guido van Rossum, Jeremy Hylton en de rest van de Python-crew voor het uitnodigen om op PyCon te spreken.