- Der Schlüssel zur Produktivität beim Programmieren liegt weniger in der Sprache selbst als in einem reichen Bibliotheks-Ökosystem
- Frameworks wie Ruby on Rails, die fortgeschrittene Sprachfunktionen nutzen, bieten selbst Nicht-Spezialisten hohe Produktivität
- Wegen struktureller Grenzen von Sprachen ist es jedoch schwierig, ein Framework auf dem Niveau von Rails in Java oder C umzusetzen
- Sprachdesign bestimmt direkt Form und Komplexität der Bibliotheken, die geschrieben werden können, und genau darin liegt der eigentliche Zweck der Weiterentwicklung von Sprachen
- Die Sprache Stanza zeigt aus dieser Perspektive, wie wichtig Sprachdesign ist, um leistungsfähige und leicht nutzbare Bibliotheken zu ermöglichen
Die Beziehung zwischen Programmiersprachen und Bibliotheken
- Die meisten Programmiersprachen besitzen ähnliche Grundelemente wie Variablen, Arrays, Schleifen und Funktionen
- Einige Sprachen bieten fortgeschrittene Funktionen wie Funktionen erster Klasse oder Coroutines, doch Nicht-Spezialisten nutzen diese kaum
- Für viele Entwickler ist der entscheidende Produktivitätsfaktor nicht die Sprache, sondern die Bibliothek
- Ruby on Rails macht es zum Beispiel leicht, datenbankgestützte Webanwendungen zu erstellen
- Dank Rails ist die Präferenz für das Framework oft größer als die für die Ruby-Sprache selbst
Das Zusammenspiel von Ruby on Rails und Sprachfunktionen
- Rails nutzt verschiedene Funktionen von Ruby wie Metaprogrammierung, Auswertung zur Laufzeit, Funktionen erster Klasse und Garbage Collection
- Beispiel: ActiveRecords verwendet Metaprogrammierung, das Template-System nutzt Laufzeitauswertung
- Die Ereignisbehandlung wird umgesetzt, indem Funktionen erster Klasse als Callbacks übergeben werden
- In Java oder C fehlen diese Fähigkeiten, sodass die Umsetzung eines Frameworks auf Rails-Niveau unmöglich ist
- Die Metaprogrammierung in Java ist nicht mächtig genug, um ActiveRecords zu implementieren
- Daher ist Rails nur dank der Struktur der Ruby-Sprache möglich, und Sprachdesign bestimmt die Möglichkeiten von Bibliotheken
Sprachdesign bestimmt die Form von Bibliotheken
- Die Sprache C unterstützt Wiederverwendung nur über Funktionsdeklaration und -aufruf, daher bestehen die meisten C-Bibliotheken aus Sammlungen von Funktionen
- Ruby unterstützt Funktionen erster Klasse und kann dadurch „welche Aktion bei einem Button-Klick ausgeführt werden soll“ knapp ausdrücken
- In Java muss man dagegen eine Handler-Klasse definieren, wodurch der Code komplexer wird
- Die Ausdrucksstärke einer Sprache bestimmt Struktur und Benutzbarkeit von Bibliotheken unmittelbar
Interaktive Software und das Aufkommen erweiterbarer Frameworks
- Im Batch-Computing der 1970er Jahre reichten funktionszentrierte Bibliotheken aus
- In moderner interaktiver Software sind erweiterbare Bibliotheken erforderlich
- In GUI- oder ereignisbasierten Systemen wird eine Struktur benötigt wie: „Führe meinen Code aus, wenn der Benutzer klickt“
- Java und C++ unterstützen Erweiterbarkeit durch Vererbung und Methodenüberschreibung, und diese Struktur entwickelte sich zu Frameworks
Hintergrund des Stanza-Designs und Grenzen von Sprachen
- Die Motivation für das Design von Stanza entstand aus der Schwierigkeit, in Java leicht nutzbare Bibliotheken für die Spieleprogrammierung zu schreiben
- In Java musste Nebenläufigkeit als Zustandsmaschine (
state machine) ausgedrückt werden - Scheme unterstützt Continuations und erlaubt dadurch eine intuitivere Umsetzung
- In Java musste Nebenläufigkeit als Zustandsmaschine (
- Scheme unterstützt jedoch keine statische Typprüfung, wodurch Debugging weniger effizient ist
- Die meisten heutigen Sprachen können ihr Typsystem nicht per Bibliothek erweitern
- Stanza bietet ein optionales Typsystem, Garbage Collection und ein auf Multimethoden basierendes Objektsystem
- Ein benutzerdefiniertes Objektsystem lässt sich jedoch nicht neu schreiben
Ziel von Sprachen und Forschungsrichtungen
- Das Ziel allgemeiner Programmiersprachen ist es, die Erstellung leistungsfähiger und leicht nutzbarer Bibliotheken zu unterstützen
- Je mächtiger eine Sprache ist, desto knapper wird die Nutzung von Bibliotheken
- Wenn Code gut entworfene Bibliotheken verwendet, besitzt er eine Natürlichkeit, als würde man einem Kollegen Anweisungen geben
- Racket, Shen und Forschungen zu Metaobjektprotokollen untersuchen erweiterbare Typ- und Objektsysteme
- Letztlich unterscheiden sich Sprachen danach, „welche Bibliotheken man nutzen kann und welche nicht“
- Hinter eleganten Bibliotheken stehen jahrzehntelange Forschung und Designarbeit an Programmiersprachen
1 Kommentare
Hacker-News-Kommentare
Das beste Beispiel ist Prolog. Es wird oft als die repräsentative Sprache des logischen Programmierens bezeichnet, ist aber in der Praxis kaum mehr als eine Sammlung verschiedener Algorithmen und könnte als Bibliothek in jeder Sprache implementiert werden. Es würde ausreichen, nur die syntaktische Ausdrucksform von Prolog an die jeweilige Syntax der einzelnen Sprachen anzupassen
Vor zehn Jahren war ich ein Scala-Fan. Das Konzept einer „Scalable Language“, in deren Typsystem man DSLs bauen kann, fand ich sehr reizvoll. Aber als die Community anfing, es wie ein Haskell auf der JVM zu verwenden, verlor ich das Interesse. Heute hoffe ich, dass Technologien wie WASM oder Graal mehr Flexibilität bei der Sprachwahl bringen. Oft reicht JS aus, aber es ist gut, jetzt auch die Option zu haben, bei Bedarf eine Low-Level-Sprache wie Rust zu verwenden
Es wäre schön, bash durch eine typisierte Skriptsprache ersetzen zu können. Ich habe einmal ein einfaches JSON-Parser-Skript in Elixir geschrieben, und das war ziemlich angenehm
#!/usr/bin/env ocamlkann man es direkt ausführen. Allerdings gibt es keine Funktion, die in einer einzelnen Datei externe Abhängigkeiten automatisch installiertSprache und Bibliothek sind nicht gegenseitig ausschließend. Manche Bibliotheken funktionieren faktisch wie eine Sprache, und umgekehrt werden manche Sprachen für bestimmte Bibliotheken entworfen. Julia ist zum Beispiel ein guter Fall für die Balance zwischen Performance und Nutzbarkeit. Man kann Hochleistungscode direkt in Julia schreiben und durch typ-spezialisierte Kompilierung auf JIT-Niveau optimierte Ausführung erhalten. Das Aufrufmodell ist einfach, intern arbeitet das System aber sehr ausgefeilt
Raku ist als Struktur entworfen, die mehrere Teilsprachen (slangs) verbindet. Reguläre Ausdrücke, PEG, Quoting und anderes werden jeweils als eigene Mini-Sprachen behandelt, und mit Slangify kann man leicht ein eigenes DSL hinzufügen
Ein Senior-Entwickler sagte einmal: „Wenn ich Rails im Lebenslauf sehe, werfe ich ihn sofort weg.“ Da habe ich wieder gemerkt, wie töricht es ist, Menschen nach einer Sprache zu beurteilen
Sprachen oder Bibliotheken sind letztlich Mittel zur Kommunikation sowohl mit Maschinen als auch mit Menschen. Mit Maschinen kommuniziert man über Bits und Spannungen, mit Menschen über Absichten und Konzepte. Wenn also eine Sprache oder Bibliothek dem Menschen eine klare und schnelle Ausdrucksform bietet, spielt es keine große Rolle, ob es sich um eine Sprache oder eine Bibliothek handelt. Rails oder Stanza — wenn es zum Zweck passt und vom Team leicht verstanden wird, ist das die richtige Antwort
Ich denke, „die Bibliothek ist die endgültige Sprache“. Ruby on Rails ist zum Beispiel eine hervorragende Sprache für Webservices auf Basis von Ruby. Ruby und Rails haben sich wechselseitig weiterentwickelt. Letztlich ist Programmierung ein fortlaufender Übersetzungsprozess von Sprache zu Sprache
Die Aussage „Je mächtiger die Sprache, desto einfacher wird die Nutzung von Bibliotheken“ stimmt. Mit dem früheren Java wäre es schwierig gewesen, ein Framework wie Express zu bauen
Wenn es um ein Web-Framework für C geht, dann gibt es doch PHP, oder? ;)