Hy 1.0 – ein Lisp-Dialekt für Python
(github.com/hylang)- Hy 1.0.0, ein in Python eingebetteter Lisp-Dialekt, wurde nach rund 12 Jahren intermittierender Entwicklung und praktischem Einsatz veröffentlicht
- In Hy 1.x führen Breaking Changes an dokumentierten Sprachelementen zu einer Erhöhung der Major-Version; ausgenommen ist das Einstellen der Unterstützung für Python-Versionen, die von den CPython-Entwicklern nicht mehr unterstützt werden
- Der künftige Fokus liegt auf neuen Bugfixes, dem Hinzufügen der Kompatibilität mit neuen Python-Versionen und der Unterstützung neuer Python-Funktionen auf eine Weise, die bestehenden Hy-1.x.y-Code nicht bricht
- Ein Nutzer nennt als Beispiel, wie sich mit Hy-Makros SQLAlchemy-ORM-Deklarationen in die Form
defmodelverkürzen lassen, und erklärt, dass es sich um eine Makro-Erweiterung handelt und daher keine zusätzlichen Laufzeitkosten entstehen - Ob Hy direkt auf MicroPython läuft, scheint wegen des Teilmengen-Umfangs der Standardbibliothek schwierig; möglich wäre aber, in CPython mit
hy2pyzu konvertieren und anschließend nur Konstrukte zu verwenden, die von MicroPython unterstützt werden
Veröffentlichung von Hy 1.0.0
- Hy 1.0.0 wurde veröffentlicht
- Hy ist ein in Python eingebetteter Lisp-Dialekt
- Bis zur Veröffentlichung gab es fast 12 Jahre intermittierende Entwicklung und viel praktischen Einsatz
- Einführung und Dokumentation gibt es auf Hylang.org
- Die Versionshistorie ist in der NEWS-Datei zu finden
- Als weniger ernster Begleittext zur Veröffentlichung ist außerdem der HYPE POST verlinkt
1.x-Kompatibilitätsrichtlinie
- Künftig führen Breaking Changes in dokumentierten Teilen der Sprache zu einer Erhöhung der Major-Version
- Eine Ausnahme gilt, wenn die Unterstützung für Python-Versionen eingestellt wird, die von den CPython-Entwicklern nicht mehr unterstützt werden
- Es wird betont, dass Major-Versionserhöhungen nicht häufig vorkommen sollen
- Der Fokus der künftigen Arbeit liegt auf Folgendem
- Beheben neu auftretender Bugs
- Hinzufügen der Kompatibilität mit neuen Python-Versionen
- Unterstützung neuer Python-Funktionen auf eine Weise, die Code nicht bricht, der in früheren Hy-1.x.y-Versionen funktioniert
Beispiel für den Einsatz von Hy-Makros: SQLAlchemy-Model-DSL
- Ein Nutzer erklärt, dass er mit Hy ein ORM und ein asynchrones Web-Framework entwickelt; beide nutzen bestehende Bibliotheken und bestehen größtenteils aus Makros
- Gezeigt wird ein Beispiel, wie sich die Modelldeklaration aus dem SQLAlchemy ORM Quick Start Guide mit dem
defmodel-Makro von Hy kürzer ausdrücken lässt- Die Modelle
UserundAddresssowie ihre Beziehungen werden in Hy-S-Expressions geschrieben defmodelist ein Makro, das zu SQLAlchemy-Code expandiert, daher entstehen keine zusätzlichen Laufzeitkosten
- Die Modelle
- Der Nutzer erklärt, dass die Stabilisierung des Hy-Kerns und der API für solche Arbeiten notwendig sei
Diskussion zu Beziehungsdeklarationen und Query-DSL
- Das
defmodel-Beispiel wird auf mehrere Beziehungsmuster erweitert- one-to-one:
1->1 - many-to-many:
*->*unddeflinktable - Zeitstempelfelder:
:timestamp-create,:timestamp-update
- one-to-one:
- Nach der Deklaration sind die Objekte normale SQLAlchemy-2.0-ORM-Objekte, sodass nur der Datenbankschema-DSL-Teil in Hy geschrieben werden kann und der Rest in Python
- An einer Query-DSL wird noch gearbeitet; es wird erwähnt, dass ein fluent interface nicht gut zu S-Expressions passt
- Ein Kommentar schlägt vor, SQL so zu gestalten, dass syntaktische und semantische Reihenfolge zusammenpassen, und verlinkt auf Google Researchs SQL Has Problems. We Can Fix Them: Pipe Syntax In SQL
- Darauf wird geantwortet, dass Formen wie
|>oder Ansätze, die list comprehensions nachahmen, möglich sein könnten, das endgültige Design aber wohl erst nach wiederholtem Bauen kleiner Apps und Refactoring entstehen werde
MicroPython-Möglichkeiten und Reaktionen auf die Veröffentlichung
- Es wird gefragt, ob Hy statt auf CPython auf MicroPython laufen könnte
- Die Antwort lautet, dass ein direkter Betrieb schwierig erscheint, weil MicroPython nur einen kleinen Teil der Python-Standardbibliothek enthält
- Allerdings könnte man mit
hy2pyin CPython zunächst in Python-Code umwandeln und das Ergebnis dann ausführen, sofern man sich auf Konstrukte beschränkt, die von MicroPython unterstützt werden - Am Tag der Veröffentlichung wurde ein starker Anstieg der täglichen einzigartigen Besucher des Webservers beobachtet, der Hylang.org hostet
1 Kommentare
Hacker-News-Kommentare
Es war etwas schwer nachzuvollziehen, wie Hy tatsächlich in Python umgewandelt wird, und anfangs war ich mir auch nicht sicher, ob es kompiliert oder interpretiert wird.
Am Ende fand ich auf Wikipedia die Erklärung, dass „Hy ein Lisp-Dialekt ist, der darauf ausgelegt ist, s-Expressions in den abstrakten Syntaxbaum (AST) von Python zu übersetzen, um mit Python zu interagieren“, und der GitHub-Code lässt vermuten, dass auch der Compiler in Python geschrieben ist: https://github.com/hylang/hy/blob/master/hy/compiler.py
Auf der Hauptseite wäre es wohl klarer, Hy als „Lisp-Dialekt, der zu Python-AST kompiliert“ zu beschreiben statt als „in Python eingebetteten Lisp-Dialekt“. Es gibt viele Möglichkeiten, Lisp einzubetten — etwa durch Anflanschen eines Interpreters, Kompilieren zu Python-Bytecode oder Umwandlung in Python-Quelltext — und die jeweiligen Trade-offs unterscheiden sich deutlich
Normalerweise wird Hy-Quellcode zu Python-AST-Objekten, und Python kompiliert und führt diese dann aus. Es ist aber auch möglich, Python-AST-Objekte in Python-Quelltext umzuwandeln, und Interoperabilität ist ebenfalls möglich, also Python in Hy oder Hy in Python zu verwenden: https://hylang.org/hy/doc/v1.0.0/interop
Am Ende wird alles zu Python-Bytecode, daher funktioniert das gut
Das sieht man etwa bei 16:25 im folgenden Video: https://m.youtube.com/watch?v=1vui-LupKJI
Während Hy über die Jahre gereift ist, scheint es eher zu einer dünnen syntaktischen Abstraktion über dem Python-Feature-Set geworden zu sein, statt immer mehr syntaktischen Zucker und Sonderfälle anzuhäufen, um lispiger und weniger pythonisch zu werden.
Der Fokus liegt also auf dem Kern, der sich anders kaum nachbilden lässt, insbesondere auf Makros. Ein aktuelles Beispiel:
matchist einfach Pythons nativesmatch, und es gibt kein Polyfill für Versionen vor Python 3.10. Früher wurdefoo?als Sonderfall zuis_foogemangelt, aber das wurde entfernt;hy.evalwurde so überarbeitet, dass es näher an Pythonsevalist; und nette, aber nicht essenzielle Utilities wieunlesswerden oft in das Paket Hyrule ausgelagert.Anfangs wirkte das kontraintuitiv, aber es hat große Vorteile: Die Lernkurve beim Wechsel von Python zu Hy wird flacher, und die Interaktion mit Python-Paketen wird konsistenter. Vielleicht geht es auch darum, die Sprachwartung zu vereinfachen; wenn ich mich richtig erinnere, brauchte es etwa vier Versuche, bis
letrichtig hinbekommen wurdeWenn ich Hy-Code schreibe, schaue ich viel öfter in die Python-Dokumentation oder in die Doku von Third-Party-Python-Bibliotheken als in die Hy-Dokumentation. Es gab viele Punkte, an denen man Python verbessern konnte, aber frühere Features wie die aus Rücksicht auf Clojure eingeführte Möglichkeit,
Truealstruezu schreiben, waren letztlich nur unnötige KomplexitätDer HYPE POST war wirklich großartig. Aus Sicht von jemandem, der im Enterprise-Software-Bereich arbeitet, ist das Satiregefühl hervorragend.
https://github.com/hylang/hy/discussions/2609
Jetzt, da es endlich draußen ist, kann ich wohl https://github.com/rcarmo/sushy aufräumen.
Ich habe über Jahre immer wieder daran herumgebastelt, aber bei jedem Hy-Upgrade gingen Teile der Syntax kaputt oder Features wanderten ins Hyrule-Paket hinein und wieder heraus, was unerquicklich war.
Nebenbei: Hy läuft auch ziemlich gut innerhalb von https://holzschu.github.io/a-Shell_iOS auf dem iPad. Allerdings muss das Syntax-Highlighting in vim/neovim noch zu den Releases ab 0.29+ und zu Async aufschließen.
Ich habe in der Zwischenzeit auch Fennel und Guile verwendet, aber der Zugriff auf Python-Bibliotheken und -Ökosysteme ist einfach besser. Dank Async kann man auch effizient mit APIs arbeiten, und in vielen Schemes ist es weiterhin umständlich, mit HTTPS zu arbeiten und dabei Sockets wiederzuverwenden sowie Header fein zu steuern, sodass ich
aiohttpdeutlich bevorzugeVerglichen mit den bescheidenen Anfängen ist das Projekt wirklich weit gekommen.
Ich habe damals den Lightning Talk auf der PyCon gesehen, in dem Hy der Welt erstmals vorgestellt wurde, und kurz darauf Paul getroffen und angefangen, zu frühen Hy-Versionen beizutragen. Ich habe mich um Common-Lisp-artige
kwargs, einige Interna und ein oder zwei Bibliotheken gekümmert.Verspieltheit ist nützlich und hilft besonders dabei, die Begeisterung aufrechtzuerhalten. Es ist schön, dass Hacker sich wie Hacker verhalten dürfen und nicht alles Business sein muss. Ich bin seit Jahren nicht mehr beteiligt, aber es freut mich zu sehen, dass das Projekt weiter vorankommt, und es fühlt sich wie ein großartiger Meilenstein an
Für Clojure-Fans gibt es in diesem Zusammenhang auch Basilisp, einen Lisp-Dialekt, der stärker auf Clojure-Kompatibilität setzt und Python 3.8+ als Ziel hat.
https://github.com/basilisp-lang/basilisp
Kein Lisp, aber aus der Perspektive einer funktionalen Programmiersprache, die nach Python transpiliert, ist auch Coconut interessant: https://coconut-lang.org/
Mich würden Erfahrungsberichte von Leuten wirklich interessieren, die Hy oder Coconut tatsächlich benutzt haben
An den Anfang des erzeugten Codes wurden massenhaft fest einkodierte Hilfsfunktionen gehängt, und das Programm war viel langsamer als wenn man denselben Inhalt in normalem Python geschrieben hätte.
Hy dagegen erzeugt, abgesehen von einer kleinen zusätzlichen Indirektion durch die Scope-Behandlung von
letoder Unterschieden rund um Rückgabewerte, Code, der ziemlich nah an Python-Code ist, den ein Mensch von Hand schreiben würde. Allerdings ist seit Coconut auch viel Zeit vergangen, also könnte es inzwischen verbessert worden seinGlückwunsch. Ich habe zwei Fragen: Unterstützt es REPL-getriebene Entwicklung, also zum Beispiel so etwas wie ein Condition System oder eine breakloop?
Außerdem würde mich interessieren, ob es eigenständig ausführbare Distributionen gibt. Schon die Verteilung von Python selbst ist umständlich, daher wäre es ideal, eine einzelne Hy-Binärdatei mit allen Abhängigkeiten ausliefern zu können. Ob statisch gelinkt oder als ZIP-Datei, die in ein temporäres Verzeichnis entpackt wird, wäre mir egal
uvx hy@1.0.0kann man in die Hy-REPL gehen.Wenn man nach
echo '(print "hi hn")' > hi.hyanschließenduvx hy@1.0.0 hi.hyausführt, wird"hi hn"ausgegeben.https://docs.astral.sh/uv/guides/tools/#running-tools
Übrigens kann uv auch Python-Versionen installieren und verwalten
Eigenständig ausführbare Distributionen gibt es nicht
Um Code interaktiv zu debuggen, kann man in den zu debuggenden Code
(.run (hy.REPL :locals {#\* (globals) #\* (locals)}))einfügen, und in Python kann man etwas wieimport hy; hy.REPL(locals = {\*globals(), \*locals()}).run()verwenden.Allerdings werden, genau wie bei
code.interact(), Änderungen an lokalen Variablen innerhalb der REPL nicht in den ursprünglichen Scope zurückübertragenpy2appund vorsichtigem Hacken habe ich schon etwas gemacht, das nahe an Punkt 2 herankommt.Man kann alles zu Bytecode kompilieren und dann Pythons Single-File-Deployment-Tools verwenden
Aber ein Condition System oder handlers/restarts gibt es nicht
Der weniger ernste Teil hat mir sehr gefallen. Ich wünschte, mehr Programmierprojekte würden Skurrilität zulassen.
Vielleicht ist das sogar die beste Art, die Python-Tradition zu ehren
Irgendwann hatte ich dann aber das Gefühl, dass wir zu weit gegangen sind, und in letzter Zeit versuchen wir, wieder ein wenig Verspieltheit zurückzubringen
Ich habe Hy immer wieder mal benutzt und auch https://github.com/kunalb/orphism veröffentlicht, das ich in Hy geschrieben habe, während ich versucht habe, einen Transformer zu bauen.
Es scheint an der Zeit zu sein, es wieder hervorzuholen und richtig laufen zu lassen