- Hurl ist eine experimentelle Programmiersprache, die den Kontrollfluss ausschließlich über Exception Handling gestaltet – statt über gewöhnliche Verzweigungen oder Schleifen
- Entstanden ist sie aus einem Gespräch zwischen Nicole Tietz-Sokolskaya und Freundinnen und Freunden vom Recurse Center; die Website bietet Dokumentation zur Nutzung, Beispiele, Debugging-Hinweise sowie Fragen und Antworten
- Die Testimonials auf der Einführungsseite stellen bewusst einen scherzhaften Ton in den Vordergrund, etwa „monstrosity is beautiful“ und „Certified unhinged™“
- Der Quellcode von Hurl und der Website ist öffentlich, aber wer Patches per E-Mail einreichen möchte, muss die Rechte am Patch abtreten
- Als Lizenz kann zwischen AGPL-3.0, GAL-1.0 und einer kommerziellen Lizenz gewählt werden
Ein Sprachexperiment, bei dem nur Exception Handling übrig bleibt
- Hurl wurde für einen einzigen Zweck geschaffen: zu erkunden, ob eine Sprache möglich ist, die ausschließlich auf Kontrollfluss auf Basis von Exception Handling beruht
- Die Idee entstand aus einem Gespräch zwischen Nicole Tietz-Sokolskaya und Freundinnen und Freunden vom Recurse Center; deren Identität wird „der Würde halber“ nicht offengelegt
- Die Website bietet Dokumentation zur Nutzung von Hurl, Beispiele, Debugging-Hinweise sowie Fragen und Antworten
Sieht wie ein Scherz aus, ist aber ein tatsächlich veröffentlichtes Projekt
- Auf der Einführungsseite stehen Testimonials, die den Charakter von Hurl zeigen
- „This monstrosity is beautiful, and I must never touch it“
- „Certified unhinged™!“
- „is "🤮" an available quote?“
- Wer weitere Testimonials aufnehmen lassen möchte, muss Nicole per E-Mail kontaktieren; für die Aufnahme des Zitats ist eine ausdrückliche Zustimmung erforderlich
Quellcode und Lizenzbedingungen
- Der Quellcode der Sprache Hurl und dieser Website ist in Hurl's repo öffentlich verfügbar
- Wer Bugs oder Fehler findet, kann Patches per E-Mail senden, muss aber alle Rechte am Patch abtreten
- Diese Bedingung dient dazu, die Möglichkeit einer Relizenzierung und einer kommerziellen Lizenz zu erhalten
- Das Projekt kann unter einer der folgenden drei Lizenzen genutzt werden
-
AGPL-3.0
- GAL-1.0: Gay Agenda License
- Kommerzielle Lizenz
- Im Zuge der Lizenzprüfung wurden auch joke licenses und unfortunate licenses in Betracht gezogen, letztlich werden jedoch die drei oben genannten Lizenzen verwendet
-
1 Kommentare
Hacker-News-Kommentare
Wenn ich eine Programmiersprache entwerfen würde, würde ich bei
include/importNamespaces erzwingen und möglichst auch Nebenwirkungen auf Top-Level-Ebene verhindernWenn man etwas wie
let foo = include "lib/foo.hurl"bekommt und dannfoo.init()aufruft, lässt sich viel leichter nachvollziehen, was passiertWenn dagegen auf
include "lib/foo.hurl" // side effectsdirektbaz(buz)folgt, ist schwer zu erkennen, ob die Funktionen und Variablen aus der Standardbibliothek stammen oder irgendwo perincludehereingekommen sindimport "foo/bar"sollte alsofoo.*oderbar.*verfügbar machen, aber nicht plötzlichbazz.*. Das erinnert direkt an GoVSCode kann mit Plugins und LSP etwas Ähnliches, ist aber deutlich schlechter. Die Code-Navigation ist so langsam, dass ich mit VSCode nicht arbeiten könnte
Ich frage mich, ob solche Vorschläge nur dann nützlich sind, wenn man solche Tools nicht hat. Zumindest im professionellen Umfeld scheint es unmöglich, ohne solche Werkzeuge auszukommen
foo.init()auch Parameter übergeben, was mit einem nackten Import nicht gehtDas heißt nicht, dass dieses Projekt wertlos ist, eher im Gegenteil: Ich sehe es als Kunstwerk
Ich habe einmal Ruby geforkt, damit
requirenicht mehr die Symboltabelle überschreibt, aber das Ruby-Ökosystem schien mir zu stark von gemeinsam genutztem globalem veränderlichem Zustand abhängig zu sein, sodass ich am Ende das Interesse an Ruby selbst verloren habeAusnahmen fand ich schon immer unerquicklich, weil sie es schwer machen, den Vertrag zwischen Aufrufer und Aufgerufenem zu verstehen, und weil sie die Kopplung im Code erhöhen
Ich bevorzuge den Ansatz von Go oder Rust, so etwas über Rückgabewerte zu behandeln. Nach einem schnellen Blick auf die Sprache ist mir nicht klar, ob es hier etwas gibt, das dieses Problem löst
Wenn eine IDE dynamisch alle nicht abgefangenen Ausnahmen einer Funktion ermitteln und zu den Stellen springen könnte, an denen eine Ausnahme ausgelöst werden kann, wäre so ein Modell vielleicht okay. Wie man dann aber die Kopplung in den Griff bekommt, weiß ich nicht, und der Kontrollflussgraph dürfte extrem instabil werden
In Java sind die Ausnahmen, die eine Funktion werfen kann, Teil der Funktionssignatur, sofern sie nicht von
RuntimeExceptionerben. In solchen Fällen kompiliert der Code nicht, wenn man eine Ausnahme wirft, ohne sie in die Signatur aufzunehmenDiese Eigenschaft von Java macht es für IDEs viel einfacher, nicht abgefangene Ausnahmen zu melden, aber bei Nicht-Runtime-Exceptions ist das letztlich ein Problem, das sich per statischer Analyse lösen lässt
Dagegen wirkt der Ansatz, standardisierte
Ok-/Err-Wrapper zurückzugeben, sowohl bei der Tool-Unterstützung als auch beim Komfort für Entwickler einfacherDer einzige Unterschied ist, dass man beim Weiterreichen von Ausnahmen den Boilerplate-Code, den der Compiler erledigen könnte, von Hand schreiben muss
Ich kann wirklich nicht nachvollziehen, warum im Jahr 2024 irgendjemand bei klarem Verstand das manuell machen wollen sollte
In der Zeit, in der ich es genutzt habe, war es viel schmerzhafter, ohne Debugger die Root Cause zu finden
Im
toss-Beispiel steht, es werde „hauptsächlich verwendet, um mehrere Werte außerhalb einer Funktion zu übergeben, sei nicht unbedingt nötig, aber irgendwie niedlich“, doch nutzlos ist es keineswegs, sondern eher eine Implementierung von fortsetzbaren GeneratorenNatürlich könnte es ziemlich interessant werden, wenn man damit auch etwas anderes tun würde als nur sofort wieder fortzusetzen. Man müsste lediglich die gesamte Codebasis als einen inneren und äußeren
toss-Stack organisierenreturnauf der Handler-Seite lexikalisch gescopet seinIn Python kann man zum Beispiel überall
next()aufrufenDas hier ist eher damit vergleichbar, einen Callback über einen Nebenkanal zu übergeben.
tossruft diesen Callback auf, undreturnkehrt dann buchstäblich von dort zurückIn anderen Sprachen wäre das eine wirklich nützliche Funktion, hier wird sie dagegen eher wie ein niedliches Feature behandelt, auf das man auch verzichten könnte. Fast schon ein Witz
yieldin C#?Hurl scheint ziemlich nahe am Condition-System von Smalltalk oder Common Lisp zu sein
Stack-Unwinding und Fortsetzen sind nur zwei mögliche Neustarts: https://gigamonkeys.com/book/beyond-exception-handling-condi...
Unabhängig vom Projekt selbst bin ich fest davon überzeugt, dass die Welt besser wäre, wenn mehr Dinge in ihrer Domain die .wtf-Erweiterung verwenden würden
Das klingt nach einer schwachen Form von algebraischen Effekten, aber es ist trotzdem cool, solche Sprachen und die Möglichkeiten damit zu sehen
Falls algebraische Effekte im Grunde so etwas wie das
toss-Keyword von Hurl sind, würde mich interessieren, worin sie mächtiger sind alstossEin interessantes Gedankenexperiment
Ich hasse Ausnahmen wirklich und möchte eine Sprache ohne Ausnahmen
Ausnahmen sind das
gotounserer ZeitSolange es
Maybe/OptionundEffect/Resultgibt, gibt es kaum einen Grund, Ausnahmen zu werfen und im Kopf nachzuverfolgen, wo sie behandelt werdenIch bin etwas besorgt, dass algebraische Effekte populärer werden und sogar das ohnehin schon viel zu komplexe Frontend-JS beeinflussen könnten. Denn sie fördern letztlich den Ansatz, zur Ablaufsteuerung „Ausnahmen“ zu werfen
Wenn das alles nur dazu dient, das Color-Problem von asynchron und synchron zu vermeiden, ist es das meiner Meinung nach überhaupt nicht wert
Wow, ich hasse das. Aber irgendwie hat es fast etwas Elegantes
Es ist sehr schwer, es im Kopf zu modellieren, aber trotzdem
Etwas ernsthafter gesprochen: Ich hätte gern syntaktisch unterschiedliche
catch-Konstrukte für fortsetzbare und nicht fortsetzbare Ausnahmen. Dann gäbe es keine syntaktische Mehrdeutigkeit mehr darüber, obreturnden Kontrollfluss zum Werfer der nächstgelegenen unmittelbaren Ausnahme zurückschickt oder nichtAußerdem sollte die Standardbibliothek nicht auf gewöhnliche Funktionen mit Rückgabewerten ausweichen. Nur weil einem das eigene Essen auf den Magen schlägt, muss man es nicht gleich aufgeben
Habe ich das richtig verstanden, dass man
hurltes abfangen kann,tosstes aber nicht? Daran müsste ich mich erst gewöhnenIch frage mich außerdem, wie viel Hurl ich schreiben muss, bis die Leute anfangen, mich einen Tosser zu nennen
Tossklingt nach einem interessanten Sprachkonstrukt. Es läuft den Stack hinauf, sucht einen Exception-Handler und kehrt dann an die ursprüngliche Stelle zurück, um die Ausführung fortzusetzen, als wäre nichts passiertDamit ließe sich zur Laufzeit offenbar zusätzliches Verhalten einschleusen
Normalerweise macht man in objektorientiertem Code Dependency Injection über Service-Konstruktoren, aber ermöglicht
tossso etwas über einen „toss-Handler“?https://koka-lang.github.io/koka/doc/book.html#why-handlers
Ich kenne mich damit nicht besonders gut aus, aber ich weiß, dass man auf diese Weise Verhalten zur Laufzeit einschleusen kann
Resume Nextin VB