Loading...

KÜRZE IST MACHT

Original

Mai 2002

"Die Menge an Bedeutung, die durch algebraische Zeichen in einen kleinen Raum komprimiert wird, ist ein weiterer Umstand, der die Überlegungen erleichtert, die wir gewohnt sind, mit ihrer Hilfe anzustellen."

  • Charles Babbage, zitiert in Iversons Turing Award Lecture

In der Diskussion über die von Revenge of the Nerds auf der LL1-Mailingliste aufgeworfenen Fragen schrieb Paul Prescod etwas, das mir im Gedächtnis geblieben ist.

Das Ziel von Python ist Regelmäßigkeit und Lesbarkeit, nicht Kürze.

Auf den ersten Blick scheint dies eine ziemlich verheerende Behauptung über eine Programmiersprache zu sein. Soweit ich das beurteilen kann, bedeutet Kürze = Macht. Wenn dem so ist, dann erhalten wir durch Substitution:

Das Ziel von Python ist Regelmäßigkeit und Lesbarkeit, nicht Macht.

und das scheint kein Kompromiss zu sein (wenn es ein Kompromiss ist), den man eingehen möchte. Es ist nicht weit davon entfernt zu sagen, dass das Ziel von Python nicht darin besteht, als Programmiersprache effektiv zu sein.

Bedeutet Kürze = Macht? Das scheint mir eine wichtige Frage zu sein, vielleicht die wichtigste Frage für jeden, der an Sprachdesign interessiert ist, und eine, die es wert wäre, direkt konfrontiert zu werden. Ich bin mir noch nicht sicher, ob die Antwort ein einfaches Ja ist, aber es scheint eine gute Hypothese zu sein, mit der man beginnen kann.

Hypothese

Meine Hypothese ist, dass Kürze Macht ist oder zumindest nah genug dran, dass man sie außer in pathologischen Beispielen als identisch betrachten kann.

Es scheint mir, dass Kürze das ist, wofür Programmiersprachen da sind. Computer wären ebenso glücklich, direkt in Maschinensprache gesagt zu bekommen, was sie tun sollen. Ich denke, der Hauptgrund, warum wir uns die Mühe machen, Hochsprachen zu entwickeln, ist, um Hebelwirkung zu erhalten, sodass wir in 10 Zeilen einer Hochsprache sagen (und wichtiger noch, denken) können, was 1000 Zeilen Maschinensprache erfordern würde. Mit anderen Worten, der Hauptpunkt von Hochsprachen ist es, den Quellcode kleiner zu machen.

Wenn kleiner Quellcode der Zweck von Hochsprachen ist und die Macht von etwas darin besteht, wie gut es seinen Zweck erfüllt, dann ist das Maß für die Macht einer Programmiersprache, wie klein sie Ihre Programme macht.

Umgekehrt macht eine Sprache, die Ihre Programme nicht klein macht, einen schlechten Job von dem, was Programmiersprachen tun sollen, wie ein Messer, das nicht gut schneidet, oder Druck, der unleserlich ist.

Metriken

Klein in welchem Sinne? Das gebräuchlichste Maß für die Größe von Code sind Zeilen Code. Aber ich denke, dass dieses Maß am gebräuchlichsten ist, weil es am einfachsten zu messen ist. Ich glaube nicht, dass irgendjemand wirklich glaubt, dass es der wahre Test für die Länge eines Programms ist. Verschiedene Sprachen haben unterschiedliche Konventionen dafür, wie viel man auf eine Zeile setzen sollte; in C haben viele Zeilen nichts weiter als ein oder zwei Trennzeichen.

Ein weiterer einfacher Test ist die Anzahl der Zeichen in einem Programm, aber das ist auch nicht sehr gut; einige Sprachen (Perl zum Beispiel) verwenden einfach kürzere Bezeichner als andere.

Ich denke, ein besseres Maß für die Größe eines Programms wäre die Anzahl der Elemente, wobei ein Element alles ist, was ein distinct node wäre, wenn man einen Baum zeichnen würde, der den Quellcode darstellt. Der Name einer Variablen oder Funktion ist ein Element; eine Ganzzahl oder eine Fließkommazahl ist ein Element; ein Segment von literalem Text ist ein Element; ein Element eines Musters oder eine Formatdirektive ist ein Element; ein neuer Block ist ein Element. Es gibt Grenzfälle (ist -5 zwei Elemente oder eines?), aber ich denke, die meisten von ihnen sind für jede Sprache gleich, sodass sie die Vergleiche nicht stark beeinflussen.

Diese Metrik muss weiter ausgearbeitet werden, und sie könnte eine Interpretation im Fall spezifischer Sprachen erfordern, aber ich denke, sie versucht, das Richtige zu messen, nämlich die Anzahl der Teile, die ein Programm hat. Ich denke, der Baum, den Sie in dieser Übung zeichnen würden, ist das, was Sie sich im Kopf vorstellen müssen, um das Programm zu begreifen, und daher ist seine Größe proportional zu dem Aufwand, den Sie betreiben müssen, um es zu schreiben oder zu lesen.

Design

Diese Art von Metrik würde es uns ermöglichen, verschiedene Sprachen zu vergleichen, aber das ist nicht, zumindest für mich, ihr Hauptwert. Der Hauptwert des Kürze-Tests ist als Leitfaden beim Designen von Sprachen. Der nützlichste Vergleich zwischen Sprachen ist zwischen zwei potenziellen Varianten derselben Sprache. Was kann ich in der Sprache tun, um Programme kürzer zu machen?

Wenn die konzeptionelle Last eines Programms proportional zu seiner Komplexität ist und ein gegebener Programmierer eine feste konzeptionelle Last tolerieren kann, dann ist das dasselbe wie zu fragen, was kann ich tun, um Programmierern zu ermöglichen, am meisten zu erreichen? Und das scheint mir identisch zu sein mit der Frage, wie kann ich eine gute Sprache entwerfen?

(Übrigens macht nichts es offensichtlicher, dass die alte Weisheit "alle Sprachen sind gleichwertig" falsch ist, als das Entwerfen von Sprachen. Wenn Sie eine neue Sprache entwerfen, vergleichen Sie ständig zwei Sprachen - die Sprache, wenn ich x mache, und wenn ich es nicht mache - um zu entscheiden, welche besser ist. Wenn dies wirklich eine bedeutungslose Frage wäre, könnten Sie ebenso gut eine Münze werfen.)

Nach Kürze zu streben, scheint ein guter Weg zu sein, neue Ideen zu finden. Wenn Sie etwas tun können, das viele verschiedene Programme kürzer macht, ist es wahrscheinlich kein Zufall: Sie haben wahrscheinlich eine nützliche neue Abstraktion entdeckt. Sie könnten sogar in der Lage sein, ein Programm zu schreiben, das hilft, indem es Quellcode nach wiederholten Mustern durchsucht. Unter anderen Sprachen wären diejenigen mit einem Ruf für Kürze die, auf die man für neue Ideen schauen sollte: Forth, Joy, Icon.

Vergleich

Die erste Person, die meines Wissens über diese Themen schrieb, war Fred Brooks in Mythical Man Month. Er schrieb, dass Programmierer anscheinend unabhängig von der Sprache etwa die gleiche Menge an Code pro Tag erzeugen. Als ich das zum ersten Mal in meinen frühen Zwanzigern las, war es eine große Überraschung für mich und schien enorme Auswirkungen zu haben. Es bedeutete, dass (a) der einzige Weg, Software schneller zu schreiben, darin bestand, eine kürzere Sprache zu verwenden, und (b) jemand, der sich die Mühe machte, dies zu tun, könnte Konkurrenten, die dies nicht taten, hinter sich lassen.

Brooks' Hypothese, wenn sie wahr ist, scheint im Herzen des Hackens zu liegen. In den Jahren seitdem habe ich auf alle Beweise geachtet, die ich zu dieser Frage bekommen konnte, von formalen Studien bis hin zu Anekdoten über einzelne Projekte. Ich habe nichts gesehen, was ihm widerspricht.

Ich habe noch keine Beweise gesehen, die mir schlüssig erschienen, und ich erwarte auch nicht, dass ich sie sehe. Studien wie Lutz Prechelts Vergleich von Programmiersprachen, die die Art von Ergebnissen erzeugen, die ich erwartet habe, neigen dazu, Probleme zu verwenden, die zu kurz sind, um bedeutungsvolle Tests zu sein. Ein besserer Test einer Sprache ist, was in Programmen passiert, die einen Monat zum Schreiben benötigen. Und der einzige echte Test, wenn Sie glauben, wie ich, dass der Hauptzweck einer Sprache darin besteht, gut zu denken (anstatt nur einem Computer zu sagen, was er tun soll, sobald Sie daran gedacht haben), ist, welche neuen Dinge Sie damit schreiben können. Daher testet jeder Sprachvergleich, bei dem Sie eine vordefinierte Spezifikation erfüllen müssen, leicht das falsche.

Der wahre Test einer Sprache ist, wie gut Sie neue Probleme entdecken und lösen können, nicht wie gut Sie sie verwenden können, um ein Problem zu lösen, das jemand anderes bereits formuliert hat. Diese beiden sind ganz unterschiedliche Kriterien. In der Kunst funktionieren Medien wie Stickerei und Mosaik gut, wenn Sie im Voraus wissen, was Sie machen möchten, sind aber absolut schlecht, wenn Sie das nicht tun. Wenn Sie das Bild entdecken möchten, während Sie es erstellen - wie Sie es mit etwas so Komplexem wie einem Bild einer Person tun müssen, zum Beispiel - müssen Sie ein flüssigeres Medium wie Bleistift oder Tusche oder Ölfarbe verwenden. Und in der Tat ist die Art und Weise, wie Wandteppiche und Mosaiken in der Praxis hergestellt werden, zuerst ein Gemälde zu machen und es dann zu kopieren. (Das Wort "Cartoon" wurde ursprünglich verwendet, um ein Gemälde zu beschreiben, das für diesen Zweck gedacht war).

Was das bedeutet, ist, dass wir wahrscheinlich nie genaue Vergleiche der relativen Macht von Programmiersprachen haben werden. Wir werden präzise Vergleiche haben, aber keine genauen. Insbesondere explizite Studien zum Zweck des Vergleichs von Sprachen, da sie wahrscheinlich kleine Probleme verwenden und notwendigerweise vordefinierte Probleme verwenden, werden dazu tendieren, die Macht der mächtigeren Sprachen zu unterschätzen.

Berichte aus der Praxis, obwohl sie notwendigerweise weniger präzise sein werden als "wissenschaftliche" Studien, sind wahrscheinlich bedeutungsvoller. Zum Beispiel führte Ulf Wiger von Ericsson eine Studie durch, die zu dem Schluss kam, dass Erlang 4-10x kürzer war als C++ und proportional schneller, um Software zu entwickeln:

Vergleiche zwischen internen Entwicklungsprojekten von Ericsson zeigen eine ähnliche Produktivität in Zeilen/Stunde, einschließlich aller Phasen der Softwareentwicklung, unabhängig davon, welche Sprache (Erlang, PLEX, C, C++ oder Java) verwendet wurde. Was die verschiedenen Sprachen unterscheidet, wird dann das Volumen des Quellcodes.

Die Studie befasst sich auch ausdrücklich mit einem Punkt, der in Brooks' Buch nur implizit war (da er die Zeilen debugged Code maß): Programme, die in mächtigeren Sprachen geschrieben sind, haben tendenziell weniger Fehler. Das wird zu einem Ziel an sich, möglicherweise wichtiger als die Produktivität des Programmierers, in Anwendungen wie Netzwerkschaltern.

Der Geschmackstest

Letztendlich denke ich, dass man auf sein Bauchgefühl hören muss. Wie fühlt es sich an, in der Sprache zu programmieren? Ich denke, der Weg, die beste Sprache zu finden (oder zu entwerfen), besteht darin, hypersensibel dafür zu werden, wie gut eine Sprache es Ihnen ermöglicht zu denken, und dann die Sprache auszuwählen/zu entwerfen, die sich am besten anfühlt. Wenn irgendein Sprachmerkmal umständlich oder einschränkend ist, machen Sie sich keine Sorgen, Sie werden es wissen.

Eine solche Hypersensibilität wird ihren Preis haben. Sie werden feststellen, dass Sie das Programmieren in umständlichen Sprachen nicht ertragen können. Ich finde es unerträglich einschränkend, in Sprachen ohne Makros zu programmieren, genau wie jemand, der an dynamische Typisierung gewöhnt ist, es unerträglich einschränkend findet, wieder in einer Sprache programmieren zu müssen, in der man den Typ jeder Variablen deklarieren muss und keine Liste von Objekten unterschiedlicher Typen erstellen kann.

Ich bin nicht der Einzige. Ich kenne viele Lisp-Hacker, denen das passiert ist. Tatsächlich könnte das genaueste Maß für die relative Macht von Programmiersprachen der Prozentsatz der Menschen sein, die die Sprache kennen und jeden Job annehmen, in dem sie diese Sprache verwenden können, unabhängig vom Anwendungsbereich.

Einschränkung

Ich denke, die meisten Hacker wissen, was es bedeutet, wenn sich eine Sprache einschränkend anfühlt. Was passiert, wenn Sie das fühlen? Ich denke, es ist dasselbe Gefühl, das Sie bekommen, wenn die Straße, die Sie nehmen möchten, gesperrt ist und Sie einen langen Umweg nehmen müssen, um dorthin zu gelangen, wo Sie hinwollten. Es gibt etwas, das Sie sagen möchten, und die Sprache lässt es nicht zu.

Was hier wirklich vor sich geht, denke ich, ist, dass eine einschränkende Sprache eine ist, die nicht kurz genug ist. Das Problem ist nicht einfach, dass Sie nicht sagen können, was Sie geplant hatten. Es ist, dass der Umweg, den die Sprache Sie nehmen lässt, länger ist. Versuchen Sie dieses Gedankenexperiment. Angenommen, es gäbe ein Programm, das Sie schreiben wollten, und die Sprache würde es Ihnen nicht erlauben, es so auszudrücken, wie Sie es geplant hatten, sondern würde Sie stattdessen zwingen, das Programm auf eine andere Weise zu schreiben, die kürzer war. Für mich zumindest würde sich das nicht sehr einschränkend anfühlen. Es wäre wie die Straße, die Sie nehmen wollten, die gesperrt ist, und der Polizist an der Kreuzung, der Sie stattdessen auf eine Abkürzung leitet. Großartig!

Ich denke, die meisten (neunzig Prozent?) des Gefühls der Einschränkung kommen davon, dass man gezwungen ist, das Programm, das man in der Sprache schreibt, länger zu machen als das, das man im Kopf hat. Einschränkung ist größtenteils ein Mangel an Kürze. Wenn sich eine Sprache also einschränkend anfühlt, bedeutet das (hauptsächlich), dass sie nicht kurz genug ist, und wenn eine Sprache nicht kurz ist, wird sie sich einschränkend anfühlen.

Lesbarkeit

Das Zitat, mit dem ich begonnen habe, erwähnt zwei andere Qualitäten, Regelmäßigkeit und Lesbarkeit. Ich bin mir nicht sicher, was Regelmäßigkeit ist oder welchen Vorteil, wenn überhaupt, Code, der regelmäßig und lesbar ist, gegenüber Code hat, der nur lesbar ist. Aber ich denke, ich weiß, was mit Lesbarkeit gemeint ist, und ich denke, es steht auch im Zusammenhang mit Kürze.

Wir müssen hier darauf achten, zwischen der Lesbarkeit einer einzelnen Codezeile und der Lesbarkeit des gesamten Programms zu unterscheiden. Es ist das zweite, das zählt. Ich stimme zu, dass eine Zeile Basic wahrscheinlich lesbarer ist als eine Zeile Lisp. Aber ein in Basic geschriebenes Programm wird mehr Zeilen haben als dasselbe Programm, das in Lisp geschrieben ist (insbesondere, wenn man in Greenspunland übergeht). Der gesamte Aufwand, das Basic-Programm zu lesen, wird sicherlich größer sein.

gesamt Aufwand = Aufwand pro Zeile x Anzahl der Zeilen

Ich bin mir nicht so sicher, dass Lesbarkeit direkt proportional zu Kürze ist, wie ich mir sicher bin, dass Macht es ist, aber sicherlich ist Kürze ein Faktor (im mathematischen Sinne; siehe obige Gleichung) in der Lesbarkeit. Es könnte also nicht einmal sinnvoll sein zu sagen, dass das Ziel einer Sprache Lesbarkeit, nicht Kürze ist; es könnte so sein, als würde man sagen, das Ziel sei Lesbarkeit, nicht Lesbarkeit.

Was Lesbarkeit pro Zeile für den Benutzer bedeutet, der der Sprache zum ersten Mal begegnet, ist, dass der Quellcode unbedrohlich aussieht. Also könnte Lesbarkeit pro Zeile eine gute Marketingentscheidung sein, auch wenn es eine schlechte Designentscheidung ist. Es ist isomorph zu der sehr erfolgreichen Technik, den Menschen zu erlauben, in Raten zu zahlen: Anstatt sie mit einem hohen Preis im Voraus zu erschrecken, sagen Sie ihnen die niedrige monatliche Zahlung. Ratenpläne sind jedoch ein Nettoverlust für den Käufer, so wie es die bloße Lesbarkeit pro Zeile wahrscheinlich für den Programmierer ist. Der Käufer wird eine Menge dieser niedrigen, niedrigen Zahlungen leisten; und der Programmierer wird eine Menge dieser einzeln lesbaren Zeilen lesen.

Dieser Kompromiss ist älter als Programmiersprachen. Wenn Sie es gewohnt sind, Romane und Zeitungsartikel zu lesen, kann Ihre erste Erfahrung beim Lesen eines Mathematikpapiers entmutigend sein. Es könnte eine halbe Stunde dauern, um eine einzige Seite zu lesen. Und doch bin ich mir ziemlich sicher, dass die Notation nicht das Problem ist, auch wenn es sich so anfühlen mag. Das Mathematikpapier ist schwer zu lesen, weil die Ideen schwer sind. Wenn Sie dieselben Ideen in Prosa ausdrücken würden (wie Mathematiker es tun mussten, bevor sie prägnante Notationen entwickelten), wären sie nicht leichter zu lesen, weil das Papier die Größe eines Buches erreichen würde.

Inwieweit?

Eine Reihe von Menschen hat die Idee abgelehnt, dass Kürze = Macht. Ich denke, es wäre nützlicher, anstatt einfach zu argumentieren, dass sie gleich oder nicht gleich sind, zu fragen: Inwieweit bedeutet Kürze = Macht? Denn offensichtlich ist Kürze ein großer Teil dessen, wofür Hochsprachen da sind. Wenn es nicht alles ist, wofür sie da sind, wofür sind sie dann noch da, und wie wichtig sind diese anderen Funktionen relativ?

Ich schlage das nicht nur vor, um die Debatte zivilisierter zu gestalten. Ich möchte wirklich die Antwort wissen. Wann, wenn überhaupt, ist eine Sprache zu kurz für ihr eigenes Wohl?

Die Hypothese, mit der ich begonnen habe, war, dass man, außer in pathologischen Beispielen, Kürze als identisch mit Macht betrachten könnte. Was ich meinte, war, dass in jeder Sprache, die jemand entwerfen würde, sie identisch wären, aber dass, wenn jemand eine Sprache entwerfen wollte, um diese Hypothese ausdrücklich zu widerlegen, er das wahrscheinlich tun könnte. Ich bin mir darüber tatsächlich nicht einmal sicher.

Sprachen, nicht Programme

Wir sollten klarstellen, dass wir über die Kürze von Sprachen sprechen, nicht von einzelnen Programmen. Es ist sicherlich möglich, dass einzelne Programme zu dicht geschrieben werden.

Ich habe darüber in On Lisp geschrieben. Ein komplexes Makro muss viele Male seine eigene Länge einsparen, um gerechtfertigt zu sein. Wenn das Schreiben eines komplizierten Makros Ihnen jedes Mal, wenn Sie es verwenden, zehn Zeilen Code sparen könnte und das Makro selbst zehn Zeilen Code ist, dann erzielen Sie eine Nettoersparnis in Zeilen, wenn Sie es mehr als einmal verwenden. Aber das könnte immer noch ein schlechter Schritt sein, weil Makrodefinitionen schwerer zu lesen sind als gewöhnlicher Code. Möglicherweise müssen Sie das Makro zehn oder zwanzig Mal verwenden, bevor es eine Nettoverbesserung in der Lesbarkeit bringt.

Ich bin mir sicher, dass jede Sprache solche Kompromisse hat (obwohl ich vermute, dass die Einsätze höher werden, je mächtiger die Sprache wird). Jeder Programmierer muss Code gesehen haben, den jemand clever gemacht hat, um ihn durch zweifelhafte Programmiertechniken marginal kürzer zu machen.

Es gibt also keinen Streit darüber - zumindest nicht von mir. Einzelne Programme können sicherlich zu kurz für ihr eigenes Wohl sein. Die Frage ist, kann eine Sprache das sein? Kann eine Sprache Programmierer dazu zwingen, Code zu schreiben, der kurz (in Elementen) auf Kosten der Gesamtlesbarkeit ist?

Ein Grund, warum es schwer vorstellbar ist, dass eine Sprache zu kurz sein könnte, ist, dass, wenn es eine übermäßig kompakte Möglichkeit gäbe, etwas auszudrücken, es wahrscheinlich auch eine längere Möglichkeit gäbe. Zum Beispiel, wenn Sie das Gefühl haben, dass Lisp-Programme, die viele Makros oder höherwertige Funktionen verwenden, zu dicht sind, könnten Sie, wenn Sie es bevorzugen, Code schreiben, der isomorph zu Pascal ist. Wenn Sie die Fakultät in Arc nicht als Aufruf einer höherwertigen Funktion ausdrücken möchten

(rec zero 1 * 1-)

könnten Sie auch eine rekursive Definition schreiben:

(rfn fact (x) (if (zero x) 1 (* x (fact (1- x)))))

Obwohl ich mir spontan keine Beispiele einfallen lassen kann, interessiert mich die Frage, ob eine Sprache zu kurz sein könnte. Gibt es Sprachen, die Sie zwingen, Code auf eine Weise zu schreiben, die krampfhaft und unverständlich ist? Wenn jemand Beispiele hat, wäre ich sehr daran interessiert, sie zu sehen.

(Erinnerung: Was ich suche, sind Programme, die gemäß der oben skizzierten Metrik "Elemente" sehr dicht sind, nicht nur Programme, die kurz sind, weil Trennzeichen weggelassen werden können und alles einen einstelligen Namen hat.)