Loading...

FÜNF FRAGEN ZUM SPRACHDESIGN

Original

Mai 2001

(Dies sind einige Notizen, die ich für eine Podiumsdiskussion über Programmiersprachen-Design am MIT am 10. Mai 2001 gemacht habe.)

1. Programmiersprachen sind für Menschen.

Programmiersprachen sind die Art und Weise, wie Menschen mit Computern kommunizieren. Der Computer wäre genauso glücklich, jede eindeutige Sprache zu sprechen. Der Grund, warum wir Hochsprachen haben, ist, dass Menschen mit Maschinensprache nicht umgehen können. Der Zweck von Programmiersprachen ist es, zu verhindern, dass unsere armen, zerbrechlichen menschlichen Gehirne von einer Fülle von Details überwältigt werden.

Architekten wissen, dass einige Arten von Gestaltungsproblemen persönlicher sind als andere. Eines der saubersten und abstraktesten Gestaltungsprobleme ist das Entwerfen von Brücken. Dort besteht Ihre Aufgabe hauptsächlich darin, eine gegebene Entfernung mit möglichst wenig Material zu überbrücken. Am anderen Ende des Spektrums steht das Entwerfen von Stühlen. Stuhldesigner müssen ihre Zeit damit verbringen, über menschliche Hintern nachzudenken.

Software variiert in ähnlicher Weise. Das Entwerfen von Algorithmen zum Routing von Daten durch ein Netzwerk ist ein schönes, abstraktes Problem, wie das Entwerfen von Brücken. Dagegen ist das Entwerfen von Programmiersprachen wie das Entwerfen von Stühlen: Es geht alles um den Umgang mit menschlichen Schwächen.

Die meisten von uns hassen es, das zuzugeben. Das Entwerfen von Systemen mit großer mathematischer Eleganz klingt für die meisten von uns viel ansprechender, als der menschlichen Schwäche zu huldigen. Und es gibt durchaus eine Rolle für mathematische Eleganz: Bestimmte Arten von Eleganz machen Programme leichter verständlich. Aber Eleganz ist kein Selbstzweck.

Und wenn ich sage, dass Sprachen so gestaltet sein müssen, dass sie menschliche Schwächen berücksichtigen, meine ich nicht, dass Sprachen für schlechte Programmierer entworfen werden 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 irgendjemand in einer Sprache programmieren möchte, 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, stellt man fest, dass viele der besten Sprachen von ihren Autoren für den eigenen Gebrauch entworfen wurden, und viele der schlechtesten Sprachen für andere Leute entworfen wurden.

Wenn Sprachen für andere Leute entworfen werden, ist es immer eine bestimmte Gruppe anderer Leute: Leute, die nicht so schlau sind wie der Sprachdesigner. Daher erhalten Sie eine Sprache, die zu Ihnen herabblickt. 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 niedrig, aber es wurde für seine Autoren entworfen, und das ist der Grund, warum Hacker es mögen.

Das Argument für das Entwerfen von Sprachen für schlechte Programmierer ist, dass es mehr schlechte Programmierer als gute Programmierer gibt. Das mag stimmen. Aber diese wenigen guten Programmierer schreiben einen unverhältnismäßig großen Teil der Software.

Mich interessiert die Frage, wie man eine Sprache entwirft, die die allerbesten Hacker mögen werden? Ich denke, das ist identisch mit der Frage, wie man eine gute Programmiersprache entwirft, aber selbst wenn dem nicht so ist, ist es zumindest eine interessante Frage.

3. Geben Sie dem Programmierer so viel Kontrolle wie möglich.

Viele Sprachen (vor allem die, die für andere Leute entworfen wurden) haben die Haltung einer Gouvernante: Sie versuchen, Sie daran zu hindern, Dinge zu tun, von denen sie denken, dass sie nicht gut für Sie sind. Ich mag den entgegengesetzten Ansatz: Geben Sie dem Programmierer so viel Kontrolle wie möglich.

Als ich Lisp zum ersten Mal lernte, gefiel mir 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, die die Sprache selbst ausmachten. Ich konnte die Sprache umschreiben, wenn ich wollte. Es hatte den gleichen Reiz 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, sieht man, dass sie sie wirklich lieben. Wie oft haben Sie Hacker liebevoll darüber sprechen hören, wie sie in APL zum Beispiel mit nur ein paar Zeilen Code erstaunliche Dinge tun konnten? Ich denke, alles, was wirklich kluge Menschen wirklich lieben, ist es wert, darauf zu achten.

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 zur Fehlergrenze knapp sein; sogar die Namen der Dinge sollten kurz sein.

Und nicht nur die Programme sollten kurz sein. Das Handbuch sollte auch dünn sein. Ein großer Teil der Handbücher besteht aus Erklärungen, Vorbehalten, Warnungen und Sonderfällen. Wenn man sich zwingt, das Handbuch zu kürzen, behebt man im besten Fall die Dinge in der Sprache, die so viel Erklärung 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 ist mit Physik verwandt, insofern als Architekten Gebäude entwerfen müssen, die nicht einstürzen, aber das eigentliche Ziel der Architekten ist es, großartige Gebäude zu bauen, nicht Entdeckungen über die Statik zu machen.

Was Hacker gerne tun, ist, großartige Programme zu schreiben. Und ich denke, zumindest in unseren 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 herkömmliche intellektuelle Währung von Forschungsarbeiten übersetzt. Intellektuell ist es genauso wertvoll, eine Sprache zu entwerfen, die Programmierer lieben werden, wie eine schreckliche zu entwerfen, die eine Idee verkörpert, über die man einen Aufsatz 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 man will, als sie selbst zu schreiben, dann tut all dieser Code nichts anderes, als das Handbuch dick zu machen. (Die Symbolics-Handbücher waren ein Paradebeispiel dafür.) Daher denke ich, dass wir an Möglichkeiten arbeiten müssen, Bibliotheken zu organisieren. Das Ideal wäre, sie so zu entwerfen, dass der Programmierer erraten kann, welcher Bibliotheksaufruf das Richtige tun würde.

2. Haben die Leute wirklich Angst vor Präfixsyntax?

Dies ist ein offenes Problem in dem Sinne, dass ich mich seit Jahren damit beschäftige und immer noch keine Antwort darauf habe. Präfixsyntax erscheint mir völlig natürlich, möglicherweise mit Ausnahme der Mathematik. Es könnte aber auch sein, dass ein Großteil der Unbeliebtheit von Lisp einfach auf eine unvertraute Syntax zurückzuführen ist. Ob man etwas dagegen unternehmen sollte, falls dies zutrifft, ist eine andere Frage.

3. Was braucht man für serverseitige Software?

Ich denke, viele der aufregendsten neuen Anwendungen, die in den nächsten zwanzig Jahren geschrieben werden, werden webbasierte Anwendungen sein, d.h. Programme, die auf dem Server sitzen und über einen Webbrowser mit Ihnen kommunizieren. Und um diese Arten von Programmen zu schreiben, brauchen wir möglicherweise einige neue Dinge.

Eines davon ist die Unterstützung für die neue Art und Weise, wie serverseitige Apps veröffentlicht werden. Anstatt ein- oder zweimal im Jahr große Veröffentlichungen wie bei Desktop-Software zu haben, werden serverseitige Apps in einer Reihe kleiner Änderungen veröffentlicht. Sie können bis zu fünf oder zehn Veröffentlichungen pro Tag haben. Und in der Regel werden immer die neueste Version verwenden.

Sie wissen, wie man Programme so gestalten kann, dass sie debuggbar sind? Nun, serverseitige Software muss ebenfalls so gestaltet sein, dass sie leicht änderbar ist. Sie müssen sie leicht ändern können, oder zumindest wissen, was eine kleine Änderung und was eine bedeutende Änderung ist.

Eine weitere Sache, die sich für serverseitige Software als nützlich erweisen könnte, sind überraschenderweise Fortsetzungen. In webbasierten Software können Sie etwas wie Fortsetzungsstil verwenden, um den Effekt von Unterprogrammen in der naturgemäß zustandslosen Welt einer Webanwendung zu erzielen. Vielleicht wäre es sinnvoll, tatsächliche Fortsetzungen 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 wirklich gerne tun würde, ist persönlich eine neue Abstraktion zu entdecken - etwas, das einen ähnlich großen Unterschied machen würde wie das Vorhandensein von Funktionen erster Klasse oder Rekursion oder sogar Schlüsselwortparametern. Das mag ein unmöglicher Traum sein. Solche Dinge werden nicht oft entdeckt. Aber ich bin immer auf der Suche.

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 der gleichen Sprache wie das Betriebssystem zu schreiben. Und so bedeutete das Schreiben von Software vor zehn Jahren im Grunde, in C zu programmieren. Schließlich entwickelte sich eine Tradition: Anwendungsprogramme dürfen nicht in ungewöhnlichen Sprachen geschrieben werden. Und diese Tradition hatte so lange Zeit, sich zu entwickeln, dass auch nicht-technische Menschen wie Manager und Risikokapitalgeber sie verinnerlicht haben.

Serverseitige Software zerstört dieses ganze Modell. Bei serverseitiger Software können Sie jede Sprache verwenden, die Sie möchten. Fast niemand versteht das noch (vor allem nicht Manager und Risikokapitalgeber). Ein paar Hacker verstehen es, und deshalb hören wir überhaupt erst von neuen, unabhängigen Sprachen wie Perl und Python. Wir hören nicht von Perl und Python, weil Leute sie verwenden, um Windows-Apps zu schreiben.

Was das für uns als an Programmiersprachen interessierte Menschen bedeutet, ist, dass es jetzt potenziell ein tatsächliches Publikum für unsere Arbeit gibt.

2. Geschwindigkeit kommt von Profiler.

Sprachdesigner oder zumindest Sprachimplementierer möchten gerne Compiler schreiben, die schnellen Code erzeugen. Aber ich glaube nicht, dass das ist, was Sprachen für Benutzer schnell macht. Knuth hat schon vor langer Zeit darauf hingewiesen, dass Geschwindigkeit nur in wenigen kritischen Engpässen wichtig ist. Und jeder, der es versucht hat, weiß, dass man diese Engpässe nicht erraten kann. Profiler sind die Antwort.

Sprachdesigner lösen das falsche Problem. Benutzer brauchen keine Benchmarks, um schnell zu sein. Was sie brauchen, ist eine Sprache, die ihnen zeigt, welche Teile ihrer eigenen Programme umgeschrieben werden müssen. Das ist es, wo die Geschwindigkeit in der Praxis herkommt. Vielleicht wäre es also ein Nettogewinn, wenn Sprachimplementierer die Hälfte der Zeit, die sie für Compiler-Optimierungen aufwenden würden, für das Schreiben eines guten Profilers verwenden würden.

3. Sie brauchen eine Anwendung, um das Design einer Sprache anzutreiben.

Das ist vielleicht keine absolute Regel, aber es scheint, als ob die besten Sprachen zusammen mit einer Anwendung entwickelt wurden, für die sie verwendet wurden. C wurde von Leuten geschrieben, die es für Systemsprogrammierung brauchten. Lisp wurde teilweise entwickelt, um symbolische Differentiation durchzuführen, und McCarthy war so ungeduldig, loszulegen, dass er schon in dem ersten Papier über Lisp von 1960 Differentiationsprogramme schrieb.

Es ist besonders gut, wenn Ihre Anwendung ein neues Problem löst. Das wird dazu tendieren, Ihre Sprache mit neuen Funktionen auszustatten, die Programmierer brauchen. Ich persönlich bin daran interessiert, eine Sprache zu schreiben, die gut für das Schreiben von serverseitigen Anwendungen geeignet ist.

[Während der Podiumsdiskussion machte auch Guy Steele diesen Punkt und schlug zusätzlich vor, dass die Anwendung nicht aus dem Schreiben des Compilers für Ihre Sprache bestehen sollte, es sei denn, Ihre Sprache ist speziell für das Schreiben von Compilern gedacht.]

4. Eine Sprache muss gut zum Schreiben von Wegwerf-Programmen geeignet sein.

Sie wissen, was ein Wegwerf-Programm ist: etwas, das Sie schnell für eine begrenzte Aufgabe schreiben. Ich denke, wenn Sie sich umschauen würden, würden Sie feststellen, dass viele große, ernsthafte Programme als Wegwerf-Programme angefangen haben. Ich wäre nicht überrascht, wenn die meisten Programme als Wegwerf-Programme begonnen hätten. Und daher, wenn Sie eine Sprache entwickeln wollen, die gut für das Schreiben von Software im Allgemeinen ist, muss sie auch gut für das Schreiben von Wegwerf- Programmen sein, denn das ist das Larvenstadium der meisten Software.

5. Syntax ist mit Semantik verbunden.

Es ist üblich, Syntax und Semantik als völlig getrennt zu betrachten. Das wird schockierend klingen, aber vielleicht sind sie es nicht. Ich denke, dass das, was Sie in Ihrer Sprache wollen, mit der Art und Weise, wie Sie es ausdrücken, zusammenhängen könnte.

Ich sprach kürzlich mit Robert Morris, und er wies darauf hin, dass Operatorüberladen 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 einen Plus-Operator für einen neuen von Ihnen erstellten Zahlentyp definieren möchten, können Sie einfach eine neue Funktion zum Addieren definieren. 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 eines Funktionsaufrufs.

1. Neue Programmiersprachen.

In den 1970er Jahren war es modern, neue Programmiersprachen zu entwerfen. In letzter Zeit war das nicht mehr der Fall. Aber ich denke, serverseitige Software wird neue Sprachen wieder modern machen. Bei serverseitiger Software können Sie jede Sprache verwenden, die Sie möchten, also wenn jemand eine Sprache entwirft, die tatsächlich besser als andere verfügbare zu sein scheint, werden es Leute wagen, sie zu verwenden.

2. Zeitteilung.

Richard Kelsey gab dies als eine Idee, deren Zeit in der letzten Runde wieder gekommen ist, und ich stimme ihm voll und ganz zu. Meine Vermutung (und die Vermutung von Microsoft, wie es scheint) ist, dass sich viel Computerei vom Desktop auf entfernte Server verlagern wird. Mit anderen Worten, Zeitteilung ist wieder da. 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 der Prozessplanung innerhalb von Scheme 48 investiert haben.

3. Effizienz.

Vor kurzem begann es den Anschein zu haben, dass Computer endlich schnell genug sind. Immer mehr hörten wir über Bytecode, was mir zumindest impliziert, dass wir glauben, Zyklen zu verschenken. Aber ich glaube nicht, dass wir das mit serverbasierter Software tun werden. Jemand muss für die Server bezahlen, auf denen die Software läuft, und die Anzahl der Nutzer, die sie pro Maschine unterstützen können, wird der Divisor ihrer Kapitalkosten sein.

Daher denke ich, dass Effizienz zumindest bei Engpässen in der Rechenleistung wichtig sein wird. Es wird besonders wichtig sein, I/O schnell durchzuführen, da serverbasierte Anwendungen viel I/O durchführen.

Es könnte sich herausstellen, dass Bytecode am Ende kein Gewinn ist. Sun und Microsoft scheinen sich gerade in einer Art Bytecode-Schlacht zu befinden. Aber sie tun das, weil Bytecode ein bequemer Ort ist, um sich in den Prozess einzuschalten, nicht weil Bytecode an sich eine gute Idee ist. Es könnte sich herausstellen, dass dieses ganze Schlachtfeld umgangen wird. Das wäre irgendwie amüsant.

1. Clients.

Das ist nur eine Vermutung, aber meine Vermutung ist, dass das siegreiche Modell für die meisten Anwendungen rein serverseitig sein wird. Software zu entwerfen, die davon ausgeht, dass jeder Ihr Client haben wird, ist wie eine Gesellschaft zu entwerfen, die davon ausgeht, dass jeder einfach ehrlich sein wird. Es wäre sicherlich bequem, aber man muss davon ausgehen, dass es niemals passieren wird.

Ich denke, es wird eine Vielzahl von Geräten geben, die eine Art Webbrowser haben, und alles, was man von ihnen annehmen kann, ist, dass sie einfaches HTML und Formulare unterstützen. Werden Sie einen Browser auf Ihrem Mobiltelefon haben? Wird es ein Telefon in Ihrem Palmtop geben? Wird Ihr Blackberry einen größeren Bildschirm bekommen? Werden Sie im Web auf Ihrem Gameboy surfen können? Auf Ihrer Uhr? Ich weiß es nicht. Und ich muss es auch nicht wissen, wenn ich darauf setze, dass alles nur auf dem Server ist. Es ist einfach so viel robuster, alle Gehirne auf dem Server zu haben.

2. Objektorientierte Programmierung.

Ich weiß, dass das ein kontroverses Thema ist, aber ich glaube nicht, dass die objektorientierte Programmierung so eine große Sache ist. Ich denke, es ist ein gutes Modell für bestimmte Arten von Anwendungen, die diese spezielle Art von Datenstruktur brauchen, wie Fenstersysteme, Simulationen und CAD-Programme. Aber ich sehe nicht, warum es das Modell für die gesamte Programmierung sein sollte.

Ich denke, ein Teil des Grundes, warum Leute in großen Unternehmen die objektorientierte Programmierung mögen, ist, dass sie viel von dem liefert, was wie Arbeit aussieht. Etwas, das natürlich als eine Liste von Ganzzahlen dargestellt werden könnte, kann jetzt als Klasse mit allerlei Gerüst und Hektik dargestellt werden.

Ein weiterer Anreiz der objektorientierten Programmierung ist, dass Methoden Ihnen einen Teil der Wirkung von Funktionen erster Ordnung geben. Aber das ist für Lisp-Programmierer alte Nachrichten. Wenn Sie tatsächlich Funktionen erster Ordnung haben, können Sie sie einfach auf die Art und Weise verwenden, die für die Aufgabe am besten geeignet ist, anstatt alles in ein Korsett von Klassen und Methoden zu zwingen.

Was das für das Sprachdesign bedeutet, denke ich, ist, dass Sie die objektorientierte Programmierung nicht zu tief einbauen sollten. Vielleicht ist die Antwort, allgemeinere, zugrunde liegende Dinge anzubieten und den Leuten zu überlassen, welche Objektsysteme sie als Bibliotheken entwerfen wollen.

3. Design by Committee.

Wenn Ihre Sprache von einem Ausschuss entworfen wird, ist das eine große Falle, und nicht nur aus den Gründen, die jeder kennt. Jeder weiß, dass Ausschüsse dazu neigen, holprige, inkonsistente Designs zu liefern. Aber ich denke, eine größere Gefahr ist, dass sie keine Risiken eingehen werden. Wenn eine Person in Charge ist, kann sie Risiken eingehen, die ein Ausschuss niemals vereinbaren würde.

Ist es notwendig, Risiken einzugehen, um eine gute Sprache zu entwerfen? Viele Leute könnten vermuten, dass Sprachdesign etwas ist, bei dem man sich ziemlich nah an der Konventionsweisheit halten sollte. Ich wette, das stimmt nicht. In allem anderen, was die Leute tun, ist der Ertrag proportional zum Risiko. Warum sollte das Sprachdesign da anders sein?