Dieser Beitrag erschien ursprünglich auf Davids Website und wird hier mit Genehmigung erneut veröffentlicht
Im vergangenen Januar kündigte Exercism ein neues Programm namens 12in23 an, bei dem die Teilnehmenden die Herausforderung bekamen, 2023 zwölf neue Programmiersprachen auszuprobieren. Jeden Monat gab es ein Thema (wie „Analytical April" oder „Object Oriented October"), und es wurden bestimmte Sprachen hervorgehoben, die man ausprobieren konnte. Ich liebe es, Neues zu lernen, und bin mit der Zeit ein ziemlicher Nerd für (Programmier-)Sprachen geworden, also beschloss ich, es auszuprobieren. 12 Sprachen, 12 Monate!
Jetzt, wo das Jahr fast vorbei ist, bin ich unglaublich zufrieden damit, wie das Projekt gelaufen ist. Ich habe erfolgreich 12 neue Sprachen ausprobiert, großartige Menschen in der Exercism-Community kennengelernt und nebenbei ein paar coole Open-Source-Beiträge beigesteuert! In diesem Beitrag gehe ich sie alle durch und erzähle, was mir jede Einzelne gebracht hat.
Sprachenauswahl
Ich habe für das Jahr ein paar Leitlinien aufgestellt, um möglichst viel aus der Erfahrung herauszuholen:
- Die Sprachen sollten für mich entweder völlig neu sein oder zumindest so unbekannt, dass ich das Gefühl hätte, eine Menge zu lernen.
- Die ausgewählten Sprachen sollten (potenziell) praktisch sein, um sie später weiter zu lernen. Dieses Projekt war nur zum Spaß, aber ich möchte meine Zeit damit verbringen, (zumindest teilweise) nützliche Dinge zu lernen.
- Ich wollte für jede Sprache, die ich nutzte, alle lokalen Tools und das VSCode-Plugin installieren. Ich wollte die Sprachen unter ungefähr gleichen Bedingungen vergleichen, mit so viel Typ-Hinweisen und IntelliSense wie möglich. Im Studium habe ich alle meine Programmierhausaufgaben in Sublime Text ohne jegliches Linting oder Autovervollständigung gemacht. Ich hatte Sorge, dass ich mich zu sehr auf diese Tools verlassen würde, wenn ich mit ihnen Programmieren lernte, und dann kein guter Programmierer wäre. Stattdessen ist das Gegenteil passiert. Je mehr Denkarbeit ich an meine Tools abgeben kann, desto mehr kann ich über das eigentliche Problem nachdenken, das gerade ansteht. Merke dir keine Dinge, merke dir, wie du sie findest.
Legen wir los!

Januar (ohne Thema)
Als der Januar begann, war das Exercism-Team noch dabei, die Monatsthemen auszuwählen, also war die Sprache dieses Monats frei wählbar. Ohne konkrete Vorgabe startete ich das Jahr mit Go. Mitte 2022 hatte ich einen Crashkurs in der Sprache gemacht, aber seitdem nicht viel damit gearbeitet und fühlte mich überhaupt nicht sicher.
Go ist eine interessante Sprache. Sein strenger Compiler sorgt dafür, dass dein Programm korrekt sein wird, und du bewegst dich keinen Millimeter, bis er glaubt, dass du es gefahrlos tun kannst.1 Sein ausführlicher Umgang mit Fehlern bedeutet, dass du nie überrascht wirst (um den Preis, dass du if err != nil { return err } so oft schreiben musst). Es gelingt ihm gut, schwierige Dinge einfach zu machen (etwa Parallelität über Channels), aber es macht auch manche einfachen Dinge schwer (String-Manipulation). Es hat eine robuste Standardbibliothek, sodass du die meisten Aufgaben ohne Fremdmodule erledigen kannst. Mir gefällt, wie viel vom Ökosystem (Formatieren, Installieren, Bauen usw.) aus erster Hand stammt und direkt im Befehl go steckt. Die Sprache hat ihre Kritiker, aber ich finde, sie erreicht ihre Ziele Korrektheit und Wartbarkeit größtenteils.
Ich hatte nicht so viel Freude an der Nutzung, dass ich sie als erste Wahl nehmen würde, aber es ist ein großartiges Tool im Werkzeugkasten für leistungsempfindliche Programme, etwa um den verschachtelten Pfad in meinem Shell-Prompt anzuzeigen.
Functional February

Februar stürzte sich gleich ins kalte Wasser mit funktionalen Sprachen, einem mathematisch angehauchten Ableger der gebräuchlicheren imperativen Programmiersprachen. Funktionale Sprachen sind bekannt für ihre „reinen" Funktionen (ohne Seiteneffekte). Ich wählte Elixir, vor allem weil mein Freund Caleb es für Advent of Code benutzt hat und davon schwärmt.
Die Zeit mit Elixir hat mir richtig gut gefallen. Es wurde von Ruby inspiriert (was Sinn ergibt; sein Schöpfer José Valim war ein Kernmitwirkender von Rails). Ich fand es einfach, funktionale Konzepte wie Methodenverkettung auszudrücken. Ich liebte den ganzen syntaktischen Zucker, der das leicht machte, etwa den Pipe-Operator (|>):
foo(bar(baz(new_function(other_function()))))
# becomes
other_function() |> new_function() |> baz() |> bar() |> foo()
Es war auch das erste Mal, dass ich mit Makros arbeitete, also mit Code, der Code schreibt. Weil sich Elixir-Programme in einem AST ausdrücken lassen, der selbst gültiger Elixir-Code ist, ist es einfach, Code zu schreiben, der anderen gültigen Code erzeugt. Das ist ein wirklich cooles Konzept, das Elixir leicht gemacht hat. Mir gefiel auch, dass Funktionen per Musterabgleich auf die Form ihrer Argumente prüfen konnten, sodass Funktionsaufrufe an die passende Implementierung weitergeleitet werden konnten:
defmodule TuplePrinter do
def print({a}) do
IO.puts("single")
IO.puts(a)
end
def print({a, b}) do
IO.puts("double")
IO.puts(a)
IO.puts(b)
end
end
TuplePrinter.print({1})
TuplePrinter.print({2, 2})
# single
# 1
# double
# 2
# 2
Es scheint die Art von Feature zu sein, die entweder großartig ist oder deinen Code zu einem einzigen Spaghetti-Haufen macht. Wie auch immer, es war ein cooles Konzept!
Elixir profitiert außerdem davon, dass es in Erlangs virtueller Maschine BEAM läuft, was ihm ein großes Ökosystem bietet, mit dem es sich austauschen kann. Es ist hervorragend in Nebenläufigkeit und der Kern des beliebten Phoenix-Web-Frameworks.
Auch wenn ich Elixir nicht sofort brauche, hat die Arbeit damit wirklich Spaß gemacht, und ich würde es auf jeden Fall wieder aufgreifen. Außerdem war es eine interessante Herausforderung, vertraute Probleme auf ungewohnte Weise anzugehen (nämlich rekursiv).
Mechanical March
März drehte sich um „System"-Sprachen, die zu Maschinencode kompiliert werden.
Von den angebotenen Möglichkeiten war Go die einzige Sprache, die mich interessierte.2 Aufmerksame Leserinnen und Leser werden bemerken, dass ich schon einen Monat mit Go verbracht hatte, also würde eine Wiederholung nicht zu meinen 12 zählen. Nun, als ich es für Januar wählte, hatten sie die Themen noch nicht angekündigt, also merkte ich nicht, dass ich mich selbst in die Ecke manövrierte.
Hätte ich gewusst, dass Bun kommt, hätte ich wahrscheinlich Zig ausprobiert, aber leider konnte ich (noch) nicht in die Zukunft sehen. Da es keine überzeugendere Wahl gab, nahm ich einen zusätzlichen Go-Monat in Kauf, wohl wissend, dass ich später im Jahr einen Doppelmonat einlegen müsste.
Analytical April
April drehte sich ganz um Sprachen, die in der Datenwissenschaft beliebt sind. Mit Python war ich zu vertraut, und R hatte ich im Studium in einem Statistikkurs gemacht (und es gefiel mir nicht), also wurde es Julia!
Die Zeit damit hat mir gefallen, aber vor allem, weil es sich Python so ähnlich anfühlte. Es war ein wenig befremdlich, wie als Amerikaner in Kanada zu sein. Alles wirkt sehr vertraut, ist aber nur ein kleines bisschen anders, auf eine Weise, die man schwer benennen kann. Plötzlich bietet dir jemand eine 2-Dollar-Münze an (oder eine Funktion, die für Matrizenrechnung wirklich wie gemacht ist), und du merkst, dass du nicht mehr in Kansas bist.
Am meisten fiel mir Julias Typsystem auf. Es wurde (optional) annotiert wie Pythons Typsystem, hatte aber Laufzeitprüfungen, um sicherzustellen, dass Argumente zu ihren deklarierten Typen passten. Ich finde, Pythons System trifft die richtige Balance zwischen Tool-Integration und dem Nicht-im-Weg-Stehen, aber ich gebe zu, dass Julias Laufzeitfehler bei falsch typisierten Funktionen ebenfalls nützlich waren.
Letztlich war Julia nett, aber ich erwarte nicht, dass ich es in Zukunft brauchen werde.
Mindshifting May
Mai legte noch einmal nach beim „Probier etwas Neues" und hob Sprachen hervor, die sehr ungewöhnliche Dinge tun. Ich nutzte die Gelegenheit, um das allseits beliebte Rust auszuprobieren. Ich muss sagen, ich verstehe den Hype.
Der berüchtigte Borrow-Checker braucht zwar sicherlich Eingewöhnung, aber mir gefiel, wie er mich dazu brachte, sorgfältiger über meine Programme nachzudenken. Der Compiler war sicher streng, aber die Fehlermeldungen halfen mir weit über das Erwartete hinaus, Probleme zu beheben. Ich will nicht behaupten, dass ich in meiner ersten Woche besonders produktiv war, aber ich habe zumindest das Gefühl, die Spitze der Lernkurve zu sehen.
cargo, Rusts Paketmanager, verdient ebenfalls besondere Erwähnung. Ich habe zwar keine Fremdpakete installiert, aber seine Funktionen zum Bauen, Testen und Formatieren waren großartig. Dasselbe gilt für die VSCode-Erweiterung, die all die Annehmlichkeiten bot, die ich von einer statisch typisierten Sprache wie Rust erwarten würde. Eine gute Developer Experience macht wirklich den ganzen Unterschied.
Auf Implementierungsebene unterscheiden sie sich sehr, aber für meine Zwecke fühlte sich Rust ähnlich an wie Go: Programme sehr schnell laufen zu lassen. Viele Tools in Sprachen, die ich regelmäßig nutze, setzen zunehmend auf Rust wegen seiner Leistungsmerkmale, also erwarte ich, es in Zukunft öfter zu sehen (auch wenn ich selbst kein Rust schreibe).
Summer of Sexps (June)
Juni war der Monat der S-Ausdrücke, einer gängigen syntaktischen Form in Lisps. Ich wählte Clojure, eine funktionale Sprache, die in der JVM läuft.
Vor vielen Jahren hatte ich ein bisschen Clojure geschrieben. Ich war frisch von der Schule und wurde in meinem ersten Job der einzige Maintainer eines geschäftskritischen täglichen Skripts. Es versteht sich von selbst, dass das eine schwierige Zeit war. Ich war gespannt, ob es zugänglicher wäre, jetzt wo ich älter und weiser war.
Ich freue mich, berichten zu können, dass es das war! Die funktionale Erfahrung im Februar half mir, rekursiv zu denken, und die Syntax war gar nicht so schlimm, wenn man sich erst einmal damit beschäftigte. Seine JVM-Interoperabilität wäre auch nützlich, wenn ich es in einem größeren Projekt einsetzen würde.
Ich sehe mich nicht wirklich Clojure für irgendetwas nutzen, solange es Alternativen gibt, aber es war keine durchweg unangenehme Erfahrung.
Nebenquest: Der Universal Test Runner!
Seit Jahren benutze ich eine kleine Bash-Funktion, um die Unit-Tests im aktuellen Verzeichnis auszuführen. Als ich mit all diesen neuen Sprachen arbeitete, ertappte ich mich dabei, dass ich ihr aus Bequemlichkeit Zeilen hinzufügte; sich zu merken, t auszuführen, war viel einfacher, als den sprachspezifischen Testbefehl immer wieder neu zu lernen.
Als die erforderliche Logik über das hinauswuchs, womit ich mich in Bash noch wohlfühlte, nahm ich mir im Juni etwas Zeit und machte das Projekt zu einer eigenen Sache: dem Universal Test Runner.
Ich teilte es im Exercism-Forum und bekam eine nette Resonanz. Es gefiel ihnen so gut, dass wir beschlossen, ähnliche Funktionalität direkt in die Exercism-CLI einzubauen (die in Go geschrieben ist, ein Thema, das ich glücklicherweise gerade aufgefrischt hatte). Also konnte ich in der zweiten Jahreshälfte exercism test ausführen, um die Testsuite für die Sprache des jeweiligen Monats laufen zu lassen (ein Befehl, der im Universal Test Runner nativ unterstützt wird).
Wenn du mehr über den Prozess erfahren möchtest, habe ich als es startete viel ausführlicher darüber geschrieben.
Wie auch immer, weiter geht's!
Jurassic July
Juli präsentierte alte Sprachen. Was die Praxisnähe anging, war die Auswahl diesen Monat ziemlich mager. Ich begann mit dem ehrwürdigen COBOL, da ich gehört hatte, dass es noch einen Großteil kritischer Infrastruktur am Laufen hält. Aber da Anfang August eine Hochzeit auf mich zukam, hatte ich nicht die Kapazität, mich hinzusetzen und eine für mich so fremde Sprache zu lernen. Stattdessen wechselte ich zu Visual Basic, der am wenigsten schlecht aussehenden Option.
Dazu gibt es nicht viel zu sagen. Die Sprache wirkte etwas ausführlich, aber einfach genug zu benutzen. Meines Wissens wurde sie eigentlich für die UI-Entwicklung unter Windows entworfen, daher fällt es schwer, sich anhand kleiner Übungen ein gutes Bild von ihr zu machen.
Appy August
August war voll von Sprachen, mit denen man Apps baut. Wenig überraschend gab es diesen Monat viele Möglichkeiten. Ich entschied mich für Swift. Als jemand, der viele Apple-Produkte benutzt, ist deren selbst entwickelte Sprache für mich ziemlich relevant. Ich war nicht völlig neu darin: 2016 hatte ich eine einzige iOS-App veröffentlicht, die rein in Swift geschrieben war. Aber seitdem hatte ich die Sprache nicht mehr angefasst, und sie hat sich stark weiterentwickelt, also dachte ich, es zählt trotzdem.
Ich war angenehm überrascht, wie einfach die Arbeit damit war. Im Gegensatz zu vielen der anderen Sprachen hier ist Swift ziemlich neu. Es wurde erstmals 2014 veröffentlicht und hat eindeutig von den Lehren des modernen Sprachdesigns profitiert. Es hat einen Paketmanager aus erster Hand, optionales Verketten, Funktionen erster Klasse und vernünftige String-Interpolation. Es fühlte sich ergonomisch an, zu lesen und zu schreiben, selbst ohne Xcode.
Trotz allem ist Swift vor allem im Kontext von Apps für Apple-Plattformen nützlich, die ich derzeit nicht schreibe. Es funktionierte gut für die Übungen, aber ich rechne nicht damit, so bald wieder darauf zurückzukommen. Ich liebe es allerdings, dass ich es auf meinem iPad schreiben kann!
Slimline September
September erkundete sehr knappe oder kleine Sprachen. Ich entschied mich für jq, ein Tool, das ich seit Jahren benutze und liebe.
Ich habe es allerdings immer nur als Werkzeug für die Arbeit mit JSON betrachtet, nicht als Allzweck-Programmiersprache. Ich war angenehm überrascht, dass es all die üblichen Ausstattungsmerkmale hat (Funktionen, Variablen, Schleifen usw.), sodass ich ziemlich komplexe Programme schreiben konnte:
# input: { "series": "1", "sliceLength": 1 }
. as {series: $series, sliceLength: $sliceLength} |
if
$series == "" then
"series cannot be empty" | halt_error
elif $sliceLength > ($series | length) then
"slice length cannot be greater than series length" | halt_error
elif $sliceLength == 0 then
"slice length cannot be zero" | halt_error
elif $sliceLength < 0 then
"slice length cannot be negative" | halt_error
else
.
end
| [range(0; $series | length)]
| map($series[. : . + $sliceLength])
| map(select(. | length == $sliceLength))
Es hat Spaß gemacht, all die jq-Funktionen auszuprobieren, die ich für einfache Datentransformationen nie gebraucht habe. Die Tools waren hier zwar etwas mangelhaft (keine Editor-Integration usw.), aber ein tieferes Verständnis für die Bandbreite von jq war wertvoll.
Nachtrag: DJ Adams hat mich auf Mastodon auf das Projekt jq-lsp und das zugehörige VSCode-Plugin aufmerksam gemacht. Diesmal habe ich den Anschluss verpasst, aber ich werde es mir künftig ansehen.
Object Oriented October
Oktober tauchte in objektorientierte Sprachen ein. Ich habe eine Schwäche für objektorientierte Entwürfe, die sehr dem entsprechen, wie ich Programme im Kopf visualisiere. Ich entschied mich für Ruby, was wie eine seltsame Wahl klingen mag.
Ich arbeite bei Stripe, der Heimat der größten Ruby-Codebasis der Welt. Das würde doch sicher nicht als „unbekannte" Sprache zählen? Das stimmt zwar alles, aber unser Ruby-Monolith fühlt sich sehr weit von „Standard"-Ruby entfernt: Alles wird mit Sorbet typgeprüft, es gibt sehr viel Codegenerierung, und wir betreiben eine Menge Magie, damit alles zusammenspielt und skaliert. Obwohl Ruby innerhalb und außerhalb von Stripe letztlich dieselbe Sprache ist, sind die Erfahrungen bei so unterschiedlichen Größenordnungen völlig verschieden; ich wollte wissen, wie das Leben draußen aussah (in den Jahren, seit ich Ruby intensiv genutzt hatte).
Größtenteils war es gut! Ruby selbst ist großartig und nennt „Programmiererglück" als Hauptziel, was bei mir Anklang fand. Mir gefällt, wie oft ich den Namen von Standardbibliotheks-Funktionen erraten kann, die ich noch nie benutzt habe. Mir gefällt, wie einfach es ist, funktionalen Code zu schreiben, und wie ergonomisch und ausdrucksstark die Syntax ist.
Allerdings war ich überrascht, wie weit die Entwicklertools hinter Python zurücklagen. Vielleicht bin ich verwöhnt, aber Typ-Hinweise direkt im Editor sowie extrem schnelles Linting und Formatieren sind mir wichtiger, als ich dachte. Für eine Sprache, die auf ihrem Höhepunkt so beliebt war wie Ruby, war ich überrascht, wie weit sie in dieser Hinsicht hinterherhinkte.3 Ich habe mich auch nie ganz an die optionalen runden Klammern bei Funktionsaufrufen gewöhnt, was das Übergeben von Funktionen als Argumente weniger geradlinig machte.
Ruby ist immer noch eine großartige Sprache, und ich werde sie bei der Arbeit weiter nutzen, aber sie leistet mir nichts, was Python nicht auch könnte, zumindest im Moment.
Nibbly November
November war der bisher schwierigste Monat: Assemblersprachen. Auch wenn es nicht mehr üblich ist, sie von Hand zu schreiben, ist es ein nützliches und interessantes Thema, mit dem man vertraut sein sollte. Ich wählte WebAssembly, weil es für das moderne und zukünftige Web wichtig ist. Es wird üblicherweise als Kompilierungsziel verwendet (und nicht von Hand geschrieben), aber es gibt Tools für die Verrückten da draußen.
Ich fühlte mich für diesen Monat unerwartet gut vorbereitet. Die Syntax fühlte sich wie Clojure an, und die Sprachstruktur wie Zachtronics' TIS-100. Seltsamerweise gefiel es mir, für jede Operation bei null anfangen zu müssen; es fühlte sich eigentümlich an. Ich würde es hassen, wenn ich auf diese Weise tatsächlich etwas erledigen müsste, aber zwischenzeitlich war es eine lustige Kuriosität. Mit großzügigen Kommentaren konnte ich etwas schreiben, das fast lesbar war:
(module
(func (export "eggCount") (param $number i32) (result i32)
(local $res i32) ;; result
(local $remainder i32) ;; loop counter
(loop $loop
;; $res =
(local.set $res
;; $res +
(i32.add
(local.get $res)
;; $number % 2
(i32.rem_u
(local.get $number)
(i32.const 2)
)
)
)
;; $number //= 2
;; (keep on stack)
(local.tee $number
(i32.div_u
(local.get $number)
(i32.const 2)
)
)
;; this will keep looping until remainder is 0
br_if $loop
)
local.get $res
)
)
Die größte Hürde war der Mangel an Doku und Ressourcen. Es war schwer, überhaupt zu erkennen, welche globalen Funktionen verfügbar waren. Aber da ich das ohnehin nicht wirklich benutzen werde, störte es mich nicht allzu sehr, sobald ich in Gang gekommen war.
Dezember schloss das Jahr mit Sprachen ab, die in keine andere Kategorie passten. Wegen des Doppelmonats im März musste ich diesen Monat zwei Sprachen abschließen.
Ich begann mit Wren. Erschaffen von Bob Nystrom, bekannt unter anderem durch Crafting Interpreters. Ich war bezaubert von seiner Liebe zum Detail, seinem geringen Umfang und seinem Top-down-Design; alles wirkt sehr durchdacht. Diese Sorgfalt zeigt sich in den Details des Variablen-Gültigkeitsbereichs und der Sichtbarkeitsregeln. Sein Compiler ist klein und reich kommentiert, also eine großartige Lernressource, wenn du dich für Sprachimplementierungen interessierst.
Wren ist etwas unausgefeilt und scheint größtenteils aufgegeben worden zu sein, aber für eine Spielzeugsprache finde ich das in Ordnung. Niemand erwartet hier Produktionsreife. Es gibt sicherlich Platz in der Welt für Nicht-Produktionssprachen.
Außerdem: Lua
Meine zweite Wahl diesen Monat war Lua. Im Gegensatz zu Wren ist es unglaublich praktisch. Seine einfache Einbettbarkeit bedeutet, dass es an vielen Stellen auftaucht, etwa beim Redis-Skripting und bei Factorio-Mods. Das Objektmodell brauchte etwas Eingewöhnung, aber ich sehe, wie ich schnell produktiv werden könnte. Ich freundete mich schnell mit Tabellen als Allzweckstruktur an. Die Tools waren gut: Der Paketmanager funktionierte sofort, und die VSCode-Erweiterung unterstützte kommentarbasierte Typannotationen ohne Umstände.
Auch wenn ich nichts habe, wofür ich Lua sofort brauche, ist es wegen seiner weiten Verbreitung ein weiteres großartiges Tool im Kasten.
Zum Abschluss

Diese Sprachtour hat mir mehr Spaß gemacht, als ich erwartet hatte. Ich habe nicht nur einige neue praktische Fähigkeiten gelernt, mein Horizont fühlt sich gründlich erweitert an.
Was als Nächstes kommt, ist wohl, viel mehr Rust zu lernen. Seine Bedeutung in der Landschaft der Entwicklertools ist mittlerweile offensichtlich, und ich möchte sicherstellen, dass ich die Dinge lesen und zu ihnen beitragen kann, auf die ich mich verlasse.
Ich habe kein konkretes Ergebnis vor Augen, aber ich habe das ganze Rust-Buch zu lesen, einen Rust-Kurs für JS-Entwickler, den ich vor einem Jahr abgerechnet habe, und einen kompletten Exercism-Track, den ich abschließen möchte. Ich möchte zu mindestens einem Open-Source-Projekt beitragen (wahrscheinlich Just, eines meiner neuen Lieblingsprogramme), aber wir werden sehen, wohin das Jahr mich führt.
Bis dahin schöne Feiertage und einen guten Rest von 2023!
-
Unbenutzte Variablen sind ein Compilerfehler?? Ich meine, echt jetzt ↩
-
Ich habe tatsächlich zuerst C++ ausprobiert (das ich seit dem Studium nicht mehr geschrieben hatte). Es hat einfach keinen Spaß gemacht, also habe ich es gelassen ↩
-
Das ist ein weiterer Punkt, in dem sich das „echte" Ruby von meiner Erfahrung bei Stripe unterscheidet, also bin ich froh, dass ich beides ausprobieren konnte ↩