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 Sprache zu sprechen, die eindeutig ist. Der Grund, warum wir höhere Programmiersprachen haben, ist, dass Menschen mit Maschinensprache nicht umgehen können. Der Sinn von Programmierung Sprachen ist es, unsere armen, zerbrechlichen menschlichen Gehirne vor Überlastung durch eine Masse von Details zu bewahren.

Architekten wissen, dass einige Arten von Designproblemen persönlicher sind als andere. Eines der saubersten, abstraktesten Designprobleme ist die Konstruktion von Brücken. Dort ist Ihre Aufgabe größtenteils eine Frage des Überbrückens einer gegebenen Distanz mit dem geringsten Material. Das andere Ende des Spektrums ist die Gestaltung von Stühlen. Stuhldesigner müssen ihre Zeit damit verbringen, über menschliche Hinterteile nachzudenken.

Software variiert auf die gleiche Weise. Die Entwicklung von Algorithmen für die Weiterleitung von Daten durch ein Netzwerk ist ein schönes, abstraktes Problem, wie die Konstruktion von Brücken. Während die Entwicklung von Programmiersprachen eher der Gestaltung von Stühlen gleicht: Es geht darum, mit menschlichen Schwächen umzugehen.

Die meisten von uns hassen es, dies zuzugeben. Die Entwicklung von Systemen von großer mathematischer Eleganz klingt für die meisten von uns viel ansprechender als das Anbiedern an menschliche 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 so konzipiert werden müssen, dass sie zu menschlichen Schwächen passen, meint das nicht, dass Sprachen für schlechte Programmierer konzipiert 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 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, waren viele der besten Sprachen, die für ihre eigenen Autoren entwickelt wurden, und viele der schlechtesten wurden für andere Menschen entwickelt.

Wenn Sprachen für andere Menschen entwickelt werden, ist es immer eine bestimmte Gruppe von anderen Menschen: Menschen, die nicht so intelligent sind wie der Sprachdesigner. So erhält man eine Sprache, die einen herablassend behandelt. Cobol ist der extremste Fall, aber viele Sprachen sind von diesem Geist durchdrungen.

Es hat nichts damit zu tun, wie abstrakt die Sprache ist. C ist ziemlich tiefgreifend, aber es wurde für seine Autoren entwickelt, und das ist der Grund, warum Hacker es mögen.

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

Ich interessiere mich für die Frage, wie man eine Sprache entwickelt, die den allerbesten Hackern gefallen wird? Ich denke, das ist identisch mit der Frage, wie man eine gute Programmiersprache entwickelt?, aber selbst wenn es das nicht ist, ist es zumindest eine interessante Frage.

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

Viele Sprachen (besonders die, die für andere Menschen entwickelt wurden) haben die Einstellung 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 die gegensätzliche Herangehensweise: 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 es gab mein Programm, geschrieben in der Sprache, und die beiden waren sehr getrennt. Aber in Lisp waren die Funktionen und Makros, die ich schrieb, genau 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 von Hackern blickt, sieht man, dass sie sie wirklich lieben. Wie oft haben Sie Hacker liebevoll darüber sprechen hören, wie sie in, sagen wir, APL, mit nur ein paar Zeilen Code erstaunliche Dinge tun konnten? Ich denke, alles, was wirklich intelligente Menschen wirklich lieben, ist es wert, darauf zu achten.

Ich denke, fast alles, was Sie tun können, 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 Unkenntlichkeit knapp sein; sogar 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 ist mit Klarstellungen und Vorbehalten und Warnungen und Sonderfällen gefüllt. Wenn Sie sich zwingen, das Handbuch zu kürzen, tun Sie es im besten Fall, indem Sie die Dinge in der Sprache beheben, 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, 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 schreiben. 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 wertvoll, eine Sprache zu entwerfen, die Programmierer lieben, wie eine schreckliche Sprache 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 einem immer wichtigeren Bestandteil 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 es dauern würde, 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 Möglichkeiten arbeiten müssen, Bibliotheken zu organisieren. Das Ideal wäre, sie so zu gestalten, dass der Programmierer erraten könnte, 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 mich seit Jahren darüber gewundert habe und immer noch nicht die Antwort kenne. Präfix-Syntax erscheint mir völlig natürlich, außer vielleicht für Mathematik. Aber es könnte sein, dass ein Großteil der Unbeliebtheit von Lisp einfach auf die ungewohnte Syntax zurückzuführen ist. Ob man etwas dagegen tun sollte, wenn es stimmt, 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 laufen und über einen Webbrowser mit Ihnen kommunizieren. Und um diese Art von Programmen zu schreiben, brauchen wir vielleicht ein paar neue Dinge.

Eines, was wir brauchen werden, ist Unterstützung für die neue Art und Weise, wie serverseitige Anwendungen veröffentlicht werden. Anstatt ein oder zwei große Veröffentlichungen pro Jahr zu haben, wie bei Desktop-Software, werden serverseitige Anwendungen als eine Reihe von kleinen Änderungen veröffentlicht. Sie können bis zu fünf oder zehn Veröffentlichungen pro Tag haben. Und in der Regel wird jeder immer die neueste Version verwenden.

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

Eine weitere Sache, die sich für serverseitige Software als nützlich erweisen könnte, überraschenderweise, sind Fortsetzungen. In webbasierter Software kann man etwas wie Continuation-Passing-Style verwenden, um den Effekt von Subroutinen in der im Wesentlichen zustandslosen Welt einer Websitzung 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 vernünftig diese Hoffnung ist, aber eines, was ich persönlich sehr gerne tun würde, ist, eine neue Abstraktion zu entdecken - etwas, das den gleichen Unterschied machen würde wie First-Class-Funktionen oder Rekursion oder sogar Schlüsselwortparameter. Das könnte ein unmöglicher Traum sein. Diese Dinge werden nicht so oft entdeckt. Aber ich bin immer auf der Suche.

1. Sie können jede Sprache verwenden, die Sie wollen.

Das Schreiben von Anwendungsprogrammen bedeutete früher, Desktop-Software zu schreiben. Und in Desktop-Software gibt es eine große Tendenz, die Anwendung in der gleichen Sprache wie das Betriebssystem zu schreiben. Und so bedeutete Softwareentwicklung vor zehn Jahren so ziemlich Softwareentwicklung in C. 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 Leute wie Manager und Risikokapitalgeber sie lernten.

Serverseitige Software sprengt dieses gesamte Modell. Mit serverseitiger Software können Sie jede beliebige Sprache verwenden. Fast niemand versteht das noch (besonders nicht Manager und Risikokapitalgeber). Ein paar Hacker verstehen es, und deshalb hören wir überhaupt von neuen, unabhängigen Sprachen wie Perl und Python. Wir hören nicht von Perl und Python, weil die Leute sie verwenden, um Windows-Anwendungen zu schreiben.

Was das für uns bedeutet, als Menschen, die sich für die Entwicklung von Programmiersprachen interessieren, ist, dass es jetzt möglicherweise ein echtes Publikum für unsere Arbeit gibt.

2. Geschwindigkeit kommt von Profilern.

Sprachdesigner, oder zumindest Sprachimplementierer, schreiben gerne Compiler, die schnellen Code erzeugen. Aber ich glaube nicht, dass das ist, was Sprachen für Benutzer schnell macht. Knuth wies schon vor langer Zeit darauf hin, dass Geschwindigkeit nur in wenigen kritischen Engstellen eine Rolle spielt. Und jeder, der es versucht hat, weiß, dass man nicht erraten kann, wo diese Engstellen liegen. Profiler sind die Antwort.

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

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

Das ist vielleicht keine absolute Regel, aber es scheint, als ob die besten Sprachen alle zusammen mit einer Anwendung entstanden sind, für die sie verwendet wurden. C wurde von Leuten geschrieben, die es für die Systemprogrammierung brauchten. Lisp wurde teilweise entwickelt, um symbolische Differentiation durchzuführen, und McCarthy war so begierig darauf, loszulegen, dass er bereits in der ersten Arbeit über Lisp, im Jahr 1960, Differentiationsprogramme schrieb.

Es ist besonders gut, wenn Ihre Anwendung ein neues Problem löst. Das wird dazu neigen, Ihre Sprache dazu zu bringen, neue Funktionen zu haben, die Programmierer brauchen. Ich persönlich bin daran interessiert, eine Sprache zu schreiben, die gut geeignet ist, um serverseitige Anwendungen zu schreiben.

[Während des Panels brachte Guy Steele diesen Punkt ebenfalls zur Sprache, mit dem zusätzlichen Vorschlag, dass die Anwendung nicht darin bestehen sollte, den Compiler für Ihre Sprache zu schreiben, es sei denn, Ihre Sprache ist zufällig für das Schreiben von Compilern gedacht.]

4. Eine Sprache muss gut geeignet sein, um Wegwerfprogramme zu schreiben.

Sie wissen, was ein Wegwerfprogramm ist: etwas, das Sie schnell für eine begrenzte Aufgabe schreiben. Ich denke, wenn Sie sich umsehen würden, würden Sie feststellen, dass viele große, ernsthafte Programme als Wegwerfprogramme begannen. Ich wäre nicht überrascht, wenn die meisten Programme als Wegwerfprogramme begannen. Und wenn Sie also eine Sprache entwickeln wollen, die gut geeignet ist, um Software im Allgemeinen zu schreiben, muss sie gut geeignet sein, um Wegwerfprogramme zu schreiben, 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 es könnte sein, dass sie es nicht sind. Ich denke, dass das, was Sie in Ihrer Sprache wollen, mit der Art und Weise zusammenhängt, wie Sie es ausdrücken.

Ich habe kürzlich mit Robert Morris gesprochen, und er wies darauf hin, dass Operatorüberladung ein größerer Gewinn in Sprachen mit Infix-Syntax ist. In einer Sprache mit Präfix-Syntax ist jede Funktion, die Sie definieren, effektiv ein Operator. Wenn Sie ein Plus für eine neue Art von Zahl definieren wollen, die 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 Aussehen zwischen der Verwendung eines überladenen Operators und einem Funktionsaufruf.

1. Neue Programmiersprachen.

In den 1970er Jahren war es modern, neue Programmiersprachen zu entwickeln. In letzter Zeit war das nicht der Fall. Aber ich denke, serverseitige Software wird neue Sprachen wieder modern machen. Mit serverseitiger Software können Sie jede beliebige Sprache verwenden, wenn also jemand eine Sprache entwickelt, die tatsächlich besser erscheint als andere, die verfügbar sind, wird es Leute geben, die ein Risiko eingehen und sie verwenden.

2. Zeitteilung.

Richard Kelsey brachte das als eine Idee ein, deren Zeit im letzten Panel wieder gekommen ist, und ich stimme ihm voll und ganz zu. Meine Vermutung (und Microsofts Vermutung, so scheint es) ist, dass ein Großteil des Rechnens vom Desktop auf entfernte Server verlagert wird. Mit anderen Worten, Zeitteilung ist zurück. Und ich denke, es wird dafür Unterstützung auf Sprachebene geben müssen. Zum Beispiel weiß ich, dass Richard und Jonathan Rees viel Arbeit in die Implementierung von Prozess- Planung innerhalb von Scheme 48 investiert haben.

3. Effizienz.

In letzter Zeit schien es, als ob Computer endlich schnell genug wären. Immer mehr hörten wir von Bytecode, was mir zumindest impliziert, dass wir das Gefühl haben, dass wir Zyklen zu verschenken haben. Aber ich glaube nicht, dass wir das mit serverseitiger Software tun 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 eine Rolle spielen wird, zumindest in rechnerischen Engstellen. Es wird besonders wichtig sein, E/A schnell zu machen, denn serverseitige Anwendungen machen viel E/A.

Es könnte sich herausstellen, dass Bytecode am Ende kein Gewinn ist. Sun und Microsoft scheinen sich im Moment in einer Art Kampf der Byte- Codes gegenüberzustehen. Aber sie tun es, weil Bytecode ein bequemer Ort ist, um sich in den Prozess einzufügen, 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 gewinnende Modell für die meisten Anwendungen rein serverseitig sein wird. Software zu entwickeln, die auf der Annahme basiert, dass jeder Ihren Client haben wird, ist wie eine Gesellschaft zu entwerfen, die auf der Annahme basiert, dass jeder einfach ehrlich sein wird. Es wäre sicherlich bequem, aber man muss davon ausgehen, dass es nie passieren wird.

Ich denke, es wird eine Vielzahl von Geräten geben, die eine Art Webzugang haben, und alles, was man über sie annehmen kann, 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 in der Lage sein, im Web auf Ihrem Gameboy zu surfen? Ihrer Uhr? Ich weiß es nicht. Und ich muss es nicht wissen, wenn ich darauf wette, dass alles einfach auf dem Server ist. Es ist einfach so viel robuster, wenn alle Gehirne auf dem Server sind.

2. Objektorientierte Programmierung.

Ich weiß, dass dies ein kontroverser Punkt ist, aber ich glaube nicht, dass 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 benötigen, wie z. B. Fenstersysteme, Simulationen und CAD-Programme. Aber ich sehe nicht ein, 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 erzeugt, was wie Arbeit aussieht. Etwas, das auf natürliche Weise als z. B. eine Liste von ganzen Zahlen dargestellt werden könnte, kann jetzt als eine Klasse mit allen möglichen Gerüsten und Hektik und Betrieb dargestellt werden.

Ein weiterer Reiz von objektorientierter Programmierung ist, dass Methoden Ihnen einen Teil des Effekts von First-Class-Funktionen geben. Aber das ist für Lisp- Programmierer alte Nachrichten. Wenn Sie tatsächliche First-Class-Funktionen haben, können Sie sie einfach auf die Weise verwenden, die für die jeweilige Aufgabe geeignet ist, anstatt alles in eine Form von Klassen und Methoden zu zwingen.

Was das für das Sprachdesign bedeutet, denke ich, ist, dass man objektorientierte Programmierung nicht zu tief einbauen sollte. Vielleicht ist die Antwort, allgemeinere, zugrunde liegende Dinge anzubieten und die Leute ihre eigenen Objekt-Systeme als Bibliotheken entwerfen zu lassen.

3. Design durch Ausschuss.

Wenn Ihre Sprache von einem Ausschuss entworfen wird, ist das ein großer Fehler, und das nicht nur aus den Gründen, die jeder kennt. Jeder weiß, dass Ausschüsse dazu neigen, klobige, inkonsistente Designs zu liefern. Aber ich denke, eine größere Gefahr ist, dass sie keine Risiken eingehen. Wenn eine Person verantwortlich ist, kann sie Risiken eingehen, auf die sich ein Ausschuss niemals einigen würde.

Ist es aber notwendig, Risiken einzugehen, um eine gute Sprache zu entwickeln? Viele Leute könnten vermuten, dass Sprachdesign etwas ist, bei dem man sich ziemlich eng an die konventionelle Weisheit halten sollte. Ich wette, das stimmt nicht. In allem anderen, was Menschen tun, ist die Belohnung proportional zum Risiko. Warum sollte Sprachdesign anders sein?