Fünf Fragen zum Sprachdesign
Mai 2001
(Dies sind einige Notizen, die ich für eine Podiumsdiskussion über das Design von Programmiersprachen am MIT am 10. Mai 2001 gemacht habe.)
1. Programmiersprachen sind für Menschen.
Programmiersprachen sind die Art und Weise, wie Menschen mit Computern sprechen. Dem Computer wäre es egal, in welcher Sprache er spricht, solange sie eindeutig ist. Der Grund, warum wir Hochsprachen haben, ist, dass Menschen keine Maschinensprache verstehen können. Der Sinn von Programmiersprachen besteht darin, zu verhindern, dass unsere armen, zerbrechlichen menschlichen Gehirne von einer Masse von Details überwältigt werden.
Architekten wissen, dass einige Designprobleme persönlicher sind als andere. Eines der saubersten, abstraktsten Designprobleme ist die Konstruktion von Brücken. Dort ist Ihre Aufgabe weitgehend eine Frage des Überspannens einer gegebenen Distanz mit dem geringsten Material. Das andere Ende des Spektrums ist das Entwerfen von Stühlen. Stuhldesigner müssen ihre Zeit damit verbringen, über menschliche Hinterteile nachzudenken.
Software variiert auf die gleiche Weise. Das Entwerfen von Algorithmen zum Weiterleiten von Daten durch ein Netzwerk ist ein schönes, abstraktes Problem, wie das Entwerfen von Brücken. Das Entwerfen von Programmiersprachen hingegen ist wie das Entwerfen von Stühlen: Es geht darum, mit menschlichen Schwächen umzugehen.
Die meisten von uns möchten das nicht wahrhaben. Das Entwerfen von Systemen von großer mathematischer Eleganz klingt für die meisten von uns viel ansprechender als das Bedienen menschlicher Schwächen. Und es gibt eine Rolle für mathematische Eleganz: Einige Arten von Eleganz machen Programme leichter verständlich. Aber Eleganz ist kein Selbstzweck.
Und wenn ich sage, dass Sprachen für menschliche Schwächen ausgelegt sein müssen, meine ich nicht, dass Sprachen für schlechte Programmierer ausgelegt sein müssen. Tatsächlich denke ich, dass man für die besten Programmierer entwerfen sollte, aber selbst die besten Programmierer haben Grenzen. Ich glaube nicht, dass jemand gerne in einer Sprache programmieren würde, in der alle Variablen der Buchstabe x mit ganzzahligen Indizes sind.
2. Entwerfen Sie für sich selbst und Ihre Freunde.
Wenn man sich die Geschichte der Programmiersprachen ansieht, wurden viele der besten Sprachen von ihren Autoren selbst entworfen, und viele der schlechtesten wurden für andere Leute entworfen.
Wenn Sprachen für andere Leute entworfen werden, sind es immer spezifische andere Leute: Leute, die nicht so schlau sind wie der Sprachdesigner. So bekommt man eine Sprache, die einen herablassend behandelt. Cobol ist der extremste Fall, aber viele Sprachen sind von diesem Geist durchdrungen.
Das hat nichts damit zu tun, wie abstrakt die Sprache ist. C ist ziemlich low-level, aber es wurde für seine Autoren entworfen, und deshalb mögen Hacker es.
Das Argument für das Entwerfen von Sprachen für schlechte Programmierer ist, dass es mehr schlechte als gute Programmierer gibt. Das mag sein. Aber diese wenigen guten Programmierer schreiben einen überproportional großen Prozentsatz der Software.
Mich interessiert die Frage, wie man eine Sprache entwirft, die die besten Hacker mögen werden? Ich glaube, das ist identisch mit der Frage, wie man eine gute Programmiersprache entwirft? Aber selbst wenn nicht, ist es zumindest eine interessante Frage.
3. Geben Sie dem Programmierer so viel Kontrolle wie möglich.
Viele Sprachen (insbesondere die für andere Leute entworfenen) haben die Haltung einer Gouvernante: Sie versuchen, Sie davon abzuhalten, Dinge zu tun, die ihrer Meinung nach nicht gut für Sie sind. Ich mag den gegenteiligen Ansatz: Geben Sie dem Programmierer so viel Kontrolle wie möglich.
Als ich Lisp zum ersten Mal lernte, mochte ich am meisten, dass es mich als gleichberechtigten Partner betrachtete. In den anderen Sprachen, die ich bis dahin gelernt hatte, gab es die Sprache und mein Programm, das in der Sprache geschrieben war, und die beiden waren sehr getrennt. Aber in Lisp waren die Funktionen und Makros, die ich schrieb, genauso wie die, aus denen die Sprache selbst bestand. Ich konnte die Sprache umschreiben, wenn ich wollte. Es hatte die gleiche Anziehungskraft wie Open-Source-Software.
4. Streben Sie nach Kürze.
Kürze wird unterschätzt und sogar verachtet. Aber wenn man in die Herzen der Hacker blickt, wird man sehen, dass sie sie wirklich lieben. Wie oft haben Sie Hacker schwärmen hören, wie sie in z.B. APL erstaunliche Dinge mit nur ein paar Zeilen Code tun konnten? Ich denke, alles, was wirklich kluge Leute wirklich lieben, ist es wert, beachtet zu werden.
Ich denke, fast alles, was man tun kann, um Programme kürzer zu machen, ist gut. Es sollte viele Bibliotheksfunktionen geben; alles, was implizit sein kann, sollte es sein; die Syntax sollte bis zum Exzess prägnant sein; selbst die Namen von Dingen sollten kurz sein.
Und nicht nur Programme sollten kurz sein. Auch das Handbuch sollte dünn sein. Ein guter Teil der Handbücher wird für Klarstellungen, Vorbehalte und Warnungen und Sonderfälle verwendet. Wenn Sie sich zwingen, das Handbuch zu kürzen, tun Sie im besten Fall, indem Sie die Dinge in der Sprache beheben, die so viele Erklärungen erforderten.
5. Geben Sie zu, was Hacking ist.
Viele Leute wünschen sich, dass Hacking Mathematik wäre, oder zumindest etwas wie eine Naturwissenschaft. Ich denke, Hacking ist eher wie Architektur. Architektur hat mit Physik zu tun, in dem Sinne, dass Architekten Gebäude entwerfen müssen, die nicht einstürzen, aber das eigentliche Ziel von Architekten ist es, großartige Gebäude zu schaffen, nicht Entdeckungen über Statik zu machen.
Was Hacker gerne tun, ist, großartige Programme zu erstellen. Und ich denke, zumindest in unseren eigenen Köpfen müssen wir uns daran erinnern, dass es eine bewundernswerte Sache ist, großartige Programme zu schreiben, auch wenn diese Arbeit sich nicht leicht in die konventionelle intellektuelle Währung von Forschungsarbeiten übersetzen lässt. Intellektuell ist es genauso lohnenswert, eine Sprache zu entwerfen, die Programmierer lieben werden, wie eine schreckliche zu entwerfen, die eine Idee verkörpert, über die man eine Arbeit veröffentlichen kann.
1. Wie organisiert man große Bibliotheken?
Bibliotheken werden zu einer immer wichtigeren Komponente von Programmiersprachen. Sie werden auch immer größer, und das kann gefährlich sein. Wenn es länger dauert, die Bibliotheksfunktion zu finden, die das tut, was Sie wollen, als sie selbst zu schreiben, dann tut all dieser Code nichts anderes, als Ihr Handbuch dick zu machen. (Die Symbolics-Handbücher waren ein Beispiel dafür.) Daher denke ich, dass wir an Wegen arbeiten müssen, Bibliotheken zu organisieren. Das Ideal wäre, sie so zu gestalten, dass der Programmierer erraten kann, welcher Bibliotheksaufruf das Richtige tun würde.
2. Haben die Leute wirklich Angst vor Präfix-Syntax?
Dies ist ein offenes Problem in dem Sinne, dass ich jahrelang darüber nachgedacht habe und immer noch keine Antwort habe. Präfix-Syntax erscheint mir vollkommen natürlich, außer vielleicht für Mathematik. Aber es könnte sein, dass ein Großteil der Unbeliebtheit von Lisp einfach auf eine ungewohnte Syntax zurückzuführen ist. Ob man etwas dagegen tun sollte, wenn es wahr ist, ist eine andere Frage.
3. Was braucht man für serverbasierte Software?
Ich denke, viele der aufregendsten neuen Anwendungen, die in den nächsten zwanzig Jahren geschrieben werden, werden webbasierte Anwendungen sein, also Programme, die auf dem Server laufen und über einen Webbrowser mit Ihnen kommunizieren. Und um diese Art von Programmen zu schreiben, benötigen wir möglicherweise einige neue Dinge.
Eine Sache, die wir brauchen werden, ist die Unterstützung für die neue Art, wie serverbasierte Apps veröffentlicht werden. Anstatt ein oder zwei große Veröffentlichungen pro Jahr zu haben, wie bei Desktop-Software, werden serverbasierte Apps als eine Reihe kleiner Änderungen veröffentlicht. Sie können so viele wie fünf oder zehn Veröffentlichungen pro Tag haben. Und in der Regel werden alle immer die neueste Version verwenden.
Sie wissen, wie man Programme so entwirft, dass sie debugbar sind? Nun, serverbasierte Software muss ebenfalls so entworfen werden, dass sie veränderbar ist. Sie müssen sie einfach ändern können, oder zumindest wissen, was eine kleine Änderung und was eine bedeutende ist.
Eine weitere Sache, die sich für serverbasierte Software als nützlich erweisen könnte, sind überraschenderweise Continuations. In webbasierter Software können Sie etwas wie Continuation-Passing-Style verwenden, um den Effekt von Unterprogrammen in der inhärent zustandslosen Welt einer Web-Sitzung zu erzielen. Vielleicht wäre es lohnenswert, tatsächliche Continuations zu haben, wenn es nicht zu teuer wäre.
4. Welche neuen Abstraktionen gibt es noch zu entdecken?
Ich bin mir nicht sicher, wie realistisch diese Hoffnung ist, aber eine Sache, die ich persönlich wirklich gerne tun würde, ist, eine neue Abstraktion zu entdecken – etwas, das einen Unterschied macht, wie erste Klasse Funktionen, Rekursion oder sogar Schlüsselwortparameter. Das mag ein unerfüllbarer Traum sein. Diese Dinge werden nicht so oft entdeckt. Aber ich halte immer Ausschau.
1. Sie können jede Sprache verwenden, die Sie möchten.
Das Schreiben von Anwendungsprogrammen bedeutete früher das Schreiben von Desktop-Software. Und bei Desktop-Software gibt es eine starke Tendenz, die Anwendung in derselben Sprache wie das Betriebssystem zu schreiben. Und so bedeutete vor zehn Jahren das Schreiben von Software weitgehend das Schreiben von Software in C. Schließlich entwickelte sich eine Tradition: Anwendungsprogramme dürfen nicht in ungewöhnlichen Sprachen geschrieben werden. Und diese Tradition hatte so viel Zeit, sich zu entwickeln, dass auch nicht-technische Leute wie Manager und Risikokapitalgeber sie lernten.
Serverbasierte Software sprengt dieses ganze Modell. Mit serverbasierter Software können Sie jede Sprache verwenden, die Sie möchten. Fast niemand versteht das noch (insbesondere nicht Manager und Risikokapitalgeber). Einige Hacker verstehen es, und deshalb hören wir sogar von neuen, unabhängigen Sprachen wie Perl und Python. Wir hören nicht von Perl und Python, weil die Leute sie zum Schreiben von Windows-Apps verwenden.
Was das für uns bedeutet, als Leute, die sich für das Design von Programmiersprachen interessieren, ist, dass es jetzt potenziell ein echtes Publikum für unsere Arbeit gibt.
2. Geschwindigkeit kommt von Profilern.
Sprachdesigner, oder zumindest Sprachimplementierer, schreiben gerne Compiler, die schnellen Code generieren. Aber ich glaube nicht, dass das die Sprachen für Benutzer schnell macht. Knuth wies schon vor langer Zeit darauf hin, dass Geschwindigkeit nur in wenigen kritischen Engpässen wichtig ist. Und jeder, der es versucht hat, weiß, dass man nicht erraten kann, wo diese Engpässe sind. Profiler sind die Antwort.
Sprachdesigner lösen das falsche Problem. Benutzer brauchen keine Benchmarks, um schnell zu laufen. Was sie brauchen, ist eine Sprache, die ihnen zeigen kann, welche Teile ihrer eigenen Programme neu geschrieben werden müssen. Dort kommt Geschwindigkeit in der Praxis her. Vielleicht wäre es also ein Netto-Gewinn, wenn Sprachimplementierer die Hälfte der Zeit, die sie für Compiler-Optimierungen aufgewendet hätten, stattdessen für das Schreiben eines guten Profilers verwenden würden.
3. Sie benötigen eine Anwendung, um das Design einer Sprache voranzutreiben.
Dies ist vielleicht keine absolute Regel, aber es scheint, dass sich die besten Sprachen alle zusammen mit einer Anwendung entwickelt haben, für die sie geschrieben wurden. C wurde von Leuten geschrieben, die es für Systemprogrammierung benötigten. Lisp wurde teilweise zur symbolischen Differentiation entwickelt, und McCarthy war so begierig darauf, anzufangen, dass er sogar in der ersten Arbeit über Lisp im Jahr 1960 Differenzierungsprogramme schrieb.
Es ist besonders gut, wenn Ihre Anwendung ein neues Problem löst. Das wird dazu neigen, Ihre Sprache zu neuen Funktionen zu treiben, die Programmierer benötigen. Ich persönlich bin daran interessiert, eine Sprache zu schreiben, die gut für die Entwicklung serverbasierter Anwendungen geeignet ist.
[Während des Panels machte Guy Steele diesen Punkt ebenfalls, mit dem zusätzlichen Vorschlag, dass die Anwendung nicht das Schreiben des Compilers für Ihre Sprache beinhalten sollte, es sei denn, Ihre Sprache ist zufällig für das Schreiben von Compilern gedacht.]
4. Eine Sprache muss gut für das Schreiben von Wegwerfprogrammen sein.
Sie wissen, was ein Wegwerfprogramm ist: etwas, das man schnell für eine begrenzte Aufgabe schreibt. Ich denke, wenn man sich umsieht, würde man feststellen, dass viele große, ernsthafte Programme als Wegwerfprogramme begonnen haben. Ich wäre nicht überrascht, wenn die meisten Programme als Wegwerfprogramme begonnen hätten. Und wenn Sie also eine Sprache erstellen möchten, die gut für das Schreiben von Software im Allgemeinen ist, muss sie gut für das Schreiben von Wegwerfprogrammen sein, denn das ist das Larvenstadium der meisten Software.
5. Syntax ist mit Semantik verbunden.
Es ist traditionell, Syntax und Semantik als völlig getrennt zu betrachten. Das wird schockierend klingen, aber es könnte sein, dass sie es nicht sind. Ich denke, was man in seiner Sprache möchte, kann damit zusammenhängen, wie man es ausdrückt.
Ich sprach kürzlich mit Robert Morris, und er wies darauf hin, dass Operatorüberladung in Sprachen mit Infix-Syntax ein größerer Gewinn ist. In einer Sprache mit Präfix-Syntax ist jede von Ihnen definierte Funktion effektiv ein Operator. Wenn Sie ein Plus für einen neuen Zahlentyp definieren möchten, den Sie sich ausgedacht haben, können Sie einfach eine neue Funktion definieren, um sie zu addieren. Wenn Sie das in einer Sprache mit Infix-Syntax tun, gibt es einen großen Unterschied im Erscheinungsbild zwischen der Verwendung eines überladenen Operators und einem Funktionsaufruf.
1. Neue Programmiersprachen.
In den 1970er Jahren war es modisch, neue Programmiersprachen zu entwerfen. In letzter Zeit war das nicht der Fall. Aber ich denke, serverbasierte Software wird neue Sprachen wieder modisch machen. Mit serverbasierter Software können Sie jede Sprache verwenden, die Sie möchten. Wenn also jemand eine Sprache entwirft, die tatsächlich besser zu sein scheint als andere verfügbare, werden Leute ein Risiko eingehen und sie benutzen.
2. Time-Sharing.
Richard Kelsey nannte dies als eine Idee, deren Zeit in der letzten Podiumsdiskussion wiedergekommen ist, und ich stimme ihm vollkommen zu. Meine Vermutung (und scheinbar auch die von Microsoft) ist, dass ein Großteil des Computings vom Desktop auf entfernte Server verlagert wird. Mit anderen Worten, Time-Sharing ist zurück. Und ich denke, es wird Unterstützung dafür auf Sprachebene geben müssen. Zum Beispiel weiß ich, dass Richard und Jonathan Rees viel Arbeit in die Implementierung von Prozess-Scheduling innerhalb von Scheme 48 gesteckt haben.
3. Effizienz.
Kürzlich schien es, dass Computer endlich schnell genug waren. Immer mehr hörten wir von Bytecode, was für mich zumindest impliziert, dass wir das Gefühl haben, Zyklen übrig zu haben. Aber ich glaube nicht, dass wir das bei serverbasierter Software haben werden. Jemand muss für die Server bezahlen, auf denen die Software läuft, und die Anzahl der Benutzer, die sie pro Maschine unterstützen können, wird der Divisor ihrer Kapitalkosten sein.
Daher denke ich, dass Effizienz wichtig sein wird, zumindest in den Rechenengpässen. Es wird besonders wichtig sein, E/A schnell zu erledigen, da serverbasierte Anwendungen viel E/A durchführen.
Es könnte sich herausstellen, dass Bytecode am Ende kein Gewinn ist. Sun und Microsoft scheinen sich im Moment in einer Art Bytecode-Schlacht gegenüberzustehen. Aber sie tun es, weil Bytecode ein bequemer Ort ist, um sich in den Prozess einzuschleichen, nicht weil Bytecode an sich eine gute Idee ist. Es könnte sich herausstellen, dass dieser ganze Schlachtfeld umgangen wird. Das wäre irgendwie amüsant.
1. Clients.
Das ist nur eine Vermutung, aber meine Vermutung ist, dass das gewinnende Modell für die meisten Anwendungen rein serverbasiert sein wird. Das Entwerfen von Software, die davon ausgeht, dass jeder Ihren Client hat, ist wie das Entwerfen einer Gesellschaft, die davon ausgeht, dass jeder ehrlich ist. Es wäre sicherlich bequem, aber man muss davon ausgehen, dass es nie passieren wird.
Ich denke, es wird eine Verbreitung von Geräten geben, die irgendeine Art von Webzugang haben, und alles, was Sie davon annehmen können, ist, dass sie einfaches HTML und Formulare unterstützen können. Werden Sie einen Browser auf Ihrem Handy haben? Wird es ein Telefon in Ihrem Palm Pilot geben? Wird Ihr Blackberry einen größeren Bildschirm bekommen? Werden Sie das Web auf Ihrem Gameboy durchsuchen können? Ihre Uhr? Ich weiß es nicht. Und ich muss es nicht wissen, wenn ich auf alles setze, was nur auf dem Server ist. Es ist einfach viel robuster, das ganze Gehirn auf dem Server zu haben.
2. Objektorientierte Programmierung.
Ich weiß, das ist ein kontroverses Thema, aber ich glaube nicht, dass objektorientierte Programmierung so wichtig ist. Ich halte es für ein gutes Modell für bestimmte Arten von Anwendungen, die diese spezifische Art von Datenstruktur benötigen, wie Fenstersysteme, Simulationen und CAD-Programme. Aber ich sehe keinen Grund, warum es das Modell für alle Programmierung sein sollte.
Ich denke, ein Teil des Grundes, warum Leute in großen Unternehmen objektorientierte Programmierung mögen, ist, dass sie viel von dem hervorbringt, was wie Arbeit aussieht. Etwas, das natürlich als eine Liste von Ganzzahlen dargestellt werden könnte, kann jetzt als Klasse mit allen Arten von Gerüsten und Aufwand und Trubel dargestellt werden.
Eine weitere Attraktion der objektorientierten Programmierung ist, dass Methoden einen Teil des Effekts von First-Class-Funktionen bieten. Aber das ist für Lisp-Programmierer nichts Neues. Wenn Sie tatsächliche First-Class-Funktionen haben, können Sie sie einfach so verwenden, wie es für die jeweilige Aufgabe am besten geeignet ist, anstatt alles in eine Form von Klassen und Methoden zu zwängen.
Was das für das Sprachdesign bedeutet, denke ich, ist, dass man objektorientierte Programmierung nicht zu tief einbauen sollte. Vielleicht ist die Antwort, allgemeinere, zugrundeliegende Dinge anzubieten und die Leute ihre eigenen Objektsysteme als Bibliotheken entwerfen zu lassen.
3. Design by Committee.
Das Design Ihrer Sprache durch ein Komitee ist eine große Gefahr, und das nicht nur aus den Gründen, die jeder kennt. Jeder weiß, dass Komitees dazu neigen, ungleichmäßige, inkonsistente Designs hervorzubringen. Aber ich denke, eine größere Gefahr ist, dass sie keine Risiken eingehen werden. Wenn eine Person verantwortlich ist, kann sie Risiken eingehen, auf die sich ein Komitee niemals einigen würde.
Ist es jedoch notwendig, Risiken einzugehen, um eine gute Sprache zu entwerfen? Viele Leute vermuten vielleicht, dass Sprachdesign etwas ist, bei dem man sich ziemlich eng an die konventionelle Weisheit halten sollte. Ich wette, das stimmt nicht. Bei allem anderen, was Menschen tun, ist die Belohnung proportional zum Risiko. Warum sollte Sprachdesign anders sein?