A Beautiful Racket

Etwas mehr als 3 Jahre nach meinem Bachelor-Abschluss an der HSLU – Informatik bin ich wieder zurück. Diesmal für den CAS «Modern Software Engineering & Development». Gelernt habe ich eine der ältesten Programmiersprachen überhaupt.

In meiner Berufstätigkeit (Java-Entwickler) bin ich nicht immer ganz so modern und schnelllebig unterwegs wie beispielsweise ein Frontend-Entwickler: die Frameworks sind seit Jahren die gleichen (Spring Boot), der Code gemäss Onkel Bob’s Clean Code  schön clean und natürlich objektorientiert.

Die Beständigkeit gibt zwar durchaus Halt in diesen turbulenten Zeiten von Blockchains und künstlicher Intelligenz, ist aber auf Dauer relativ langweilig. Aus diesem Grund freute ich mich umso mehr auf diesen CAS, der ja das Wort „modern“ bereits im Titel trägt. Welche wundersamen neuen Programmierparadigmen wurden wohl in den letzten drei Jahren erfunden? Hat jemand TempleOS in Rust nachimplementiert?

Die ersten Eindrücke waren jedoch etwas anders. Man erklärte uns was Skript-Sprachen sind, was genau „agil“ bedeutet und was für UML-Diagramme es alles gibt (immernoch die gleichen wie im Studium). Fast alle Themen waren zwar relevant und einige sogar interessant (Modularisierung, Parallelisierung), aber insgesamt nicht sehr viel Neues für mich. Bis auf zwei Inputs, die grausamerweise frühmorgens an einem Samstag stattfanden:

  • Functional Programming (schon mal gehört)
  • Formal Software Verification (noch nie gehört)

Mit „Formal Verification“ ist im Kontext von Software Systemen gemeint, dass man (mathematisch) beweisen kann, dass ein System korrekt ist. Das Ganze ist sehr aufwändig und kompliziert, weshalb es sich nicht für eine normale Web App eignet. Für die Raumfahrt oder Verschlüsselungsprotokolle ist es aber durchaus interessant. Besonders spannend war für mich aber die Art, wie eine Software verifiziert wird.

Das „formal proof management system“ Coq bietet eine Sprache (ebenfalls Coq) an, mit der sich mathematische Definition, Algorithmen etc. überprüfen lassen. Dafür gibt es auch eine Version, die man direkt im Browser ausprobieren kann. Die Syntax ist exotisch, der Code enthält sonderbare Zeichen… hier gibt es definitiv noch etwas Neues zu Lernen!

Weil ich aber weder Kryptograf noch Raketenbauer bin, habe ich mich nicht vertieft mit der Software Verification auseinandergesetzt, sondern mit dieser Sprache „Coq“. Woher kommt sie, warum sieht sie so aus, wie sie aussieht? Nach kurzer Online-Recherche wusste ich etwas mehr: Coq ist in OCaml geschrieben, eine Sprache aus der ML-Familie (wie bespielsweise auch Haskell). Das erklärt zumindest die Syntax.

Meine Recherche führte mich aber noch weiter: Coq ist eine sogenannte „Domain-specific language“,  kurz DSL, weil sie eben spezifisch für einen bstimmten Anwendungsfall ist (hier Software Verification). Bekannte DSLs sind beispielsweise HTML für Webseiten und SQL für Datenbank-Abfragen. Gemäss Wikipedia werden einfachere DSLs auch informell als „mini-languages“ bezeichnet. Als ich das gelesen habe, war mir sofort klar, was ich mit dem angebrochenen Samstagnachmittag machen will: ich bastle eine eigene Programmiersprache!

Das geht zum Glück ganz einfach und ist in meinem neuen Lieblingsbuch „Beautiful Racket“ Schritt für Schritt beschrieben. Der Titel bedeutet auf Deutsch „schöner Schläger“, bezieht sich aber vermutlich eher auf die Programmiersprache Racket. Das Buch beschreibt, wie man mit Racket eigene kleine DSL erstellen kann. Diesen Ansatz nennt man „language-oriented programming„. Sprachen sind hier ebenfalls nur Software und somit auch nicht anderes, als ein weiterer Baustein wie es auch Funktionen, Objekte oder Module sind. Statt ein Problem direkt zu lösen, baut man eine (sehr) spezifische, eigene Sprache und löst dann das Problem damit.

Das erste Beispiel im Buch ist die Programmiersprache „Stacker“. Es handelt sich um einen einfachen Taschenrechner, der alle Argumente (Zahlen und Operanden) in einen Stack ablegt und dann der Reihe nach (d.h. in umgekehrter polnischer Notation) verarbeitet. Das geht mit erstaunlich wenig Code gibt einen guten Überblick über die wichtigsten Konzepte:

  • Reader: Konvertiert Source Code von Text in sogenannte S-Expressions (Datenstruktur in Lisp, kann sowohl Daten als auch Code enthalten).
  • Expander: Bestimmt, wie diese S-Expressions in Racket-Befehle umgewandelt werden und führt diese dann aus.

Dieses erste Beispiel wird dann im folgenden Kapitel überarbeitet, in dem dieses einfache Programm (die Sprache „Stacker“) umgeschrieben wird in einen funktionalen Stil. Der Stack wird abgelöst durch verschachtelte Funktionsaufrufe und das Zwischenresultat in einem Akkumulator zwischgespeichert. Das neue Programm heisst „Funstacker“ und kann genau gleich viel wie das alte. Aber der Code ist kürzer, lesbarer und einfacher erweiterbar, wenn man sich einmal an die Syntax gewöhnt hat.

Racket basiert auf Scheme, was wiederum ein Dialekt von Lisp ist. Während man die Prinzipien des „Language-oriented programming“ kennenlernt,wird man nebenbei noch mit den Grundsätzen und Vorzügen der funktionalen Programmierung belohnt und lernt auch noch Lisp, eine rund 60 Jahre alte Programmiersprache. Besser kann man einen Samstagnachmittag kaum verbringen!

 

 

Beitrag teilen

Pascal J. Kiser

Bloggt aus dem Unterricht des CAS «Modern Software Engineering & Development»

Alle Beiträge ansehen von Pascal J. Kiser →

Schreibe einen Kommentar