39 Punkte von xguru 2022-12-12 | 7 Kommentare | Auf WhatsApp teilen

Was ist eine „Little Language“?

  • „Kleine Sprachen“ sind Sprachen, die mit dem Ziel entwickelt wurden, ein bestimmtes Problem zu lösen
    → SQL, RegEx, Dhall, ..
    → Sie werden auch DSLs genannt

Warum brauchen wir kleine Sprachen?

  • Anwendungen sind viel komplexer geworden, und damit ist auch der Quellcode gewachsen – zugleich ist er schwerer zu verstehen
  • Das Onboarding neuer Mitarbeiter ist schwierig, Fehler entstehen durch mangelndes Verständnis von Abhängigkeiten, und Codeänderungen werden immer schwerer zu verwalten
  • In den letzten 10 Jahren sind Codebasen um das 100- bis 500-Fache gewachsen
    • Der Linux-Kernel begann 1992 mit 10.000 Zeilen und erreichte 20 Jahre später 30 Millionen Zeilen
  • Solcher Code ist nicht nur deshalb entstanden, „weil es mehr Funktionen gibt“. Sondern weil sich verändert hat, wie wir Software bauen
    • Software ähnelt dem Bau einer Pyramide: Für den letzten Stein braucht man unten noch viel mehr Steine

Den Trend überwinden

  • Braucht man wirklich unbedingt Millionen von Codezeilen, um ein modernes OS zu bauen?
  • Alan Kay stellte diese Annahme 2006 im STEPS-Programm infrage
  • Wir glauben, dass das Erschaffen von „Sprachen“, die zu den Problemen passen, die wir lösen müssen, die Problemlösung erleichtert und Lösungen sowohl verständlicher als auch kleiner macht

  • Im STEPS-Projekt wurde eine Sprache namens Nile entwickelt, mit der ein Cairo-Renderer mit ähnlicher Funktionalität aus etwa 300 Zeilen Code statt 44.000 Zeilen umgesetzt wurde

Warum reichen Hochsprachen nicht aus?

  • Warum erstellt man nicht einfach eine allgemeinere Sprache auf noch höherem Niveau?
  • Ich persönlich denke, dass wir bei der Ausdruckskraft allgemeiner Programmiersprachen einen Punkt abnehmender Grenzerträge erreicht haben
  • Wie würde eine noch höhere Sprache aussehen? Nimmt man Python als Beispiel, wirkt sie schon heute so hochabstrakt, dass sie fast wie Pseudocode aussieht
  • Das Problem allgemeiner Sprachen ist, dass man sein Problem erst in einen Algorithmus übersetzen und diesen Algorithmus dann in der Zielsprache ausdrücken muss
    • In Jon Bentleys Programming Pearls von 1986 wurden Donald Knuth und Doug McIlroy gebeten, ein Programm zum Zählen von Worthäufigkeiten zu schreiben. Don schrieb über zehn Seiten hinweg in WEB, einer Pascal-Variante, mit komplexen Datenstrukturen
    • Doug dagegen löste es mit einer sechszeiligen Unix-Pipeline unter Verwendung von tr, sort, uniq, sort, sed usw.

Weniger ist mehr

  • Die obigen Unix-Befehle zeigen eine weitere Eigenschaft kleiner Sprachen.
    „Weniger mächtige Sprache und mächtigere Runtime“
  • Gonzalez spricht in „The end of history for programming“ über diesen Trend
    • Probleme aus dem User-Space werden in Runtime-Probleme verschoben
      • Programme werden eher zu reinen mathematischen Ausdrücken, während die Komplexität der Runtime stark zunimmt
  • Reguläre Ausdrücke und SQL können jeweils nichts anderes ausdrücken als Textsuche bzw. Datenbankarbeit
  • Das steht im Kontrast zu Sprachen wie C, die keine Runtime haben und in denen sich alles ausdrücken lässt
  • Kleine Sprachen stehen am entgegengesetzten Ende des Machtspektrums von C
    • Sie abstrahieren nicht nur die Computerarchitektur, sondern beschränken auch die Arten von Programmen, die sich ausdrücken lassen, und sind deshalb per Design Turing-unvollständig
    • Das klingt sehr restriktiv, eröffnet aber eine neue Dimension von Möglichkeiten für Optimierung und statische Analyse

Statische Analyse

  • Weniger mächtige Sprachen lassen sich leichter analysieren und können stärkere Garantien liefern als allgemeine Programmiersprachen
  • Dhall ist zum Beispiel eine „Total Functional Programming Language“ zum Erzeugen von Konfigurationsdateien
    • Das heißt: Um das Risiko unendlicher Schleifen auszuschließen, „garantieren“ Dhall-Programme, dass sie „(1) nicht abstürzen und (2) in endlicher Zeit terminieren“
    • (1) wird dadurch erreicht, dass keine Exceptions geworfen werden. Operationen, die fehlschlagen können, geben ein Optional-Ergebnis zurück (ein Wert kann vorhanden sein oder nicht)
    • (2) wird dadurch erreicht, dass rekursive Definitionen nicht erlaubt sind
  • In anderen funktionalen Sprachen ist Rekursion die Standardmethode zur Implementierung von Schleifen, aber Dhall muss sich auf eingebaute fold-Funktionen verlassen
  • Dass es keine allgemeinen Schleifenkonstrukte gibt, bedeutet, dass Dhall nicht Turing-vollständig ist. Aber das muss es auch nicht sein, da es keine allgemeine Programmiersprache ist
  • Wenn eine Sprache klein ist, wird Schlussfolgern deutlich einfacher
    • Es ist zum Beispiel schwierig zu prüfen, ob ein Python-Programm keine anderen Seiteneffekte hat, während es bei SQL genügt zu prüfen, ob die Query mit SELECT beginnt
  • Im Fall von Nile brauchte das STEPS-Team einen grafischen Debugger und baute deshalb einen; hier kann man ihn direkt ansehen
    • Das ist möglich, weil Nile eine kleine Sprache ist, über die sich leicht schlussfolgern lässt

Die Notwendigkeit von Geschwindigkeit

  • Mächtigere Programmiersprachen erhöhen nicht nur die Wahrscheinlichkeit von Bugs, sondern können auch der Performance schaden
  • Wenn ein Programm zum Beispiel nicht als Algorithmus ausgedrückt wird, kann die Runtime den Algorithmus selbst wählen
    • Langsame Ausdrücke können durch schnelle ersetzt werden (unter der Voraussetzung, dass man beweisen kann, dass sie dasselbe Ergebnis liefern)
  • Eine SQL-Query schreibt zum Beispiel nicht vor, wie sie ausgeführt werden soll
    • Die Datenbank-Engine kann frei entscheiden, welcher Query-Plan geeignet ist
      • Ob ein Index, ein zusammengesetzter Index oder ein vollständiger Scan der gesamten DB-Tabelle verwendet wird usw.
    • Moderne Datenbank-Engines sammeln auch Statistiken über die Werteverteilung in jeder Spalte und können daher on the fly einen statistisch optimalen Query-Plan wählen
    • Wäre die Query in Form eines Algorithmus gegeben, wäre das nicht möglich
  • Eine der „geheimen Zutaten“, die die Nile-Sprache so kompakt machten, war „Jitblt“, ein Just-in-Time-Compiler für Grafik-Rendering
    • In Gesprächen zwischen dem STEPS- und dem Cairo-Team wurde klar, dass viel Cairo-Code darauf verwendet wurde, Pixel-Composition manuell zu optimieren
    • Diese Arbeit ließ sich theoretisch an einen Compiler auslagern
    • Dan Amelang aus dem Cairo-Team meldete sich freiwillig, um einen solchen Compiler zu implementieren – daraus entstand Jitblt
    • Dadurch konnte die Optimierungsarbeit der Grafik-Pipeline von der reinen mathematischen Beschreibung dessen getrennt werden, was gerendert werden soll,
      und so konnte Nile genauso schnell laufen wie der ursprüngliche handoptimierte Cairo-Code

Small languages, Big Potential (kleine Sprachen, großes Potenzial)

  • Was wurde also aus STEPS? Wurde ein OS gebaut, das in so wenig Code lief, dass es auf ein T-Shirt passt?
  • Das Endergebnis von STEPS war KSWorld
    • Ein vollständiges OS mit eingebautem Dokumenteneditor und Tabellenkalkulation
    • 17.000 Zeilen Code
    • Ein bisschen zu lang für ein T-Shirt, aber ich halte es trotzdem für einen Erfolg
  • Die Entstehung von KSWorld zeigt, dass „kleine Sprachen“ großes Potenzial haben
  • Dennoch bleiben viele Fragen offen
    • Wie sprechen diese Sprachen miteinander?
    • Sollten sie in eine gemeinsame Intermediate Representation kompiliert werden?
    • Oder sollten verschiedene Runtimes parallel existieren und über Standardprotokolle kommunizieren (wie Unix-Pipes oder TCP/IP)?
    • Oder sind die einzelnen Sprachen klein genug, dass sie sich in mehreren Hostsprachen neu implementieren lassen?
    • Oder ist vielleicht eine Kombination aus all dem der richtige Weg nach vorn?
  • Ich bin jedenfalls überzeugt, dass wir uns andere Wege ausdenken müssen, Software zu bauen
    • Vielleicht werden „kleine Sprachen“ ein Teil dieser Geschichte sein
    • Wichtig ist, dass wir nicht einfach immer weiter Ziegel auf Ziegel stapeln, sondern lange genug innehalten, um uns etwas Besseres vorstellen zu können

7 Kommentare

 
ide127 2022-12-15

"
Wir denken, dass es die Problemlösung erleichtert, eine zur jeweils zu lösenden Aufgabe passende „Sprache“ zu schaffen, und dass die Lösung dadurch verständlicher und zugleich kleiner wird.
"

Beim Lesen dieses Abschnitts hatte ich den Eindruck, dass „kleine Sprachen“ am Ende nicht vielleicht dasselbe wie Frameworks meinen. So wie im Fall „JavaScript -> React“, wo häufig verwendete Funktionen und Designmuster erzwungen und dadurch gewissermaßen zu einer Art Grammatik gemacht werden.

 
chicol 2022-12-14

Ein interessantes Thema.

 
kunggom 2022-12-12

Mir fällt gerade ein, dass ich vor Kurzem ein DSL-Erstellungstool namens MPS (Meta Programming System) entdeckt habe, das von JetBrains entwickelt wurde.
Offenbar gibt es das schon deutlich länger, als ich dachte. Es hat mein Interesse geweckt, und ich wollte es mir genauer ansehen, habe es aber aus verschiedenen Gründen immer wieder aufgeschoben. Falls jemand damit Erfahrung hat, würde ich mich freuen, so etwas wie einen Erfahrungsbericht dazu zu hören.

 
uglyduck68 2022-12-12

Wow, danke.

 
nicewook 2022-12-12

Ich habe es mit Dank gelesen.

 
roxie 2022-12-12

Lisp ist ganz aus dem Häuschen

 
xguru 2022-12-12

Ich finde, das ist eine interessante Geschichte, deshalb teile ich sie hier.