- Eine kleine Sprache, die Syntax im Rust-Stil verwendet und auf der Go-Laufzeit läuft, also die Stärken beider Sprachen kombiniert
- Eine Struktur, die Sicherheit und Ausdrucksstärke durch algebraische Datentypen, Pattern Matching, ein Hindley-Milner-Typsystem und standardmäßige Unveränderlichkeit stärkt
- Gewährleistet Interoperabilität mit dem Go-Ökosystem durch direkten Import von Go-Paketen, den Pipeline-Operator, try-Blöcke und task-basierte Nebenläufigkeit
- Verbessert Developer Experience und Code-Stabilität durch Fehlererkennung zur Compile-Zeit, klare Diagnosemeldungen und LSP-Unterstützung
- Zentral ist, dass Lisette-Code in klar lesbaren Go-Code umgewandelt wird und sich dadurch natürlich in bestehende Go-Projekte integrieren lässt
Überblick über Lisette
- Lisette ist eine kleine Sprache, die auf Rust-Syntax basiert und in die Go-Laufzeit kompiliert wird
- Zu den Merkmalen gehören algebraische Datentypen, Pattern Matching, kein nil, ein Hindley-Milner-Typsystem, standardmäßige Unveränderlichkeit und Interoperabilität mit dem Go-Ökosystem
- Die Installation ist mit dem Befehl
cargo install lisettemöglich; außerdem lassen sich Go-Pakete wiefmt,ioundosdirekt importieren und verwenden
Vertraute Syntax
- Besitzt eine Rust-ähnliche Syntaxstruktur
- Unterstützt Pattern Matching mit
enumundmatch - Mit
struct- undimpl-Blöcken lassen sich Methoden definieren
- Unterstützt Pattern Matching mit
- Als ausdrucksorientierte Sprache geben
if,letund Blöcke allesamt Werte zurück - Unterstützt Chaining und Lambdas, sodass sich die Verarbeitung von Umgebungsvariablen oder String-Manipulationen kompakt ausdrücken lässt
- Unterstützt Interfaces und Generics; generische Funktionen können mit
interface-Definitionen undT: Trait-Constraints geschrieben werden - Mit if let- und let else-Syntax lässt sich der
Option-Typ kompakt behandeln
Sicherheit
-
Erkennt mögliche Fehler der Go-Laufzeit bereits zur Compile-Zeit
- Wenn in einer
match-Anweisung nicht alle Muster behandelt werden, tritt ein Fehler auf nilkann nicht verwendet werden; fehlende Werte werden mit Option<T> dargestellt- Wird ein Result-Rückgabewert ignoriert, erscheint eine Warnung
- Wird ein nicht öffentlicher Typ in einer öffentlichen API offengelegt, erscheint eine Warnung
- Wird eine unveränderliche Variable an ein veränderliches Argument übergeben, entsteht ein Fehler
- Fehlen Struct-Felder, führt das zu einem Compile-Fehler
- Diagnosemeldungen liefern zusammen mit konkreten Code-Positionen auch Korrekturvorschläge
- Dank LSP (Language Server Protocol) wird die Nutzung in wichtigen Editoren wie VSCode, Neovim und Zed unterstützt
- Wenn in einer
Nutzbarkeit
- Mit Fokus auf Interoperabilität mit Go entworfen
- Der Pipeline-Operator (
|>) drückt Function Chaining kompakt aus - try-Blöcke vereinfachen die Fehlerweitergabe
- Nebenläufigkeit wird mit
taskundChannelumgesetzt, ähnlich wie Goroutines in Go - Über Serialisierungsattribute (attribute) lassen sich JSON-Feldnamen, Auslassung, String-Konvertierung und Validierungs-Tags festlegen
- Bietet einen
recover-Block zur Wiederherstellung nach panics; mit demResult-Typ ist sichere Fehlerbehandlung möglich - Unterstützt die
defer-Syntax, um Ressourcenbereinigung oder Transaction-Rollback sicherzustellen
Transparente Compiler-Ergebnisse
- Lisette-Code wird in klaren und gut lesbaren Go-Code umgewandelt
Option- undResult-Typen werden jeweils inlisette.Option- bzw.lisette.Result-Structs umgewandeltmatch-Syntax wird in Go-Bedingungsanweisungen umgewandelt, die die einzelnen Zweige verarbeiten- Der
?-Operator wird intern durch Code zur Prüfung vonResultersetzt
- Im Beispiel nimmt die Funktion
classifyeinOption<int>entgegen und wird in explizite Go-Bedingungsanweisungen umgewandelt; die Funktioncombinewird in Go-Code übersetzt, derResultprüft
Weitere Informationen
- Offizielles Repository: github.com/ivov/lisette
- Veröffentlicht unter der MIT-Lizenz; entwickelt laut Stand 2026 von Iván Ovejero
1 Kommentare
Hacker-News-Kommentare
Ich habe mit dem Autor gesprochen und die Sprache selbst zwar nicht ausprobiert, aber Lisette wirkt interessant und wie eine klare Verbesserung gegenüber Go.
Trotzdem glaube ich, dass sich die Grenzen von Go nicht vollständig überwinden lassen. Zum Beispiel wird das
typed nil-Problem aus Gos Interface-Typen in Lisette mit Option behandelt, aber doppeltes Unwrapping (Some(Some(h))) kann sich unbeholfen anfühlen.Außerdem ist Gos defer-Ansatz weiterhin unpraktisch und bietet keine automatische Ressourcenfreigabe wie RAII.
TypeScript hat JavaScript deshalb ergänzt, weil es keine Alternative gab, die im Browser laufen konnte; mit WASM ist die Lage heute anders.
Daher stellt sich die Frage: „Warum Go wie Rust machen, wenn es bereits Rust gibt?“ Allerdings scheint Lisette genau auf diese Zwischenposition zu zielen.
Letztlich wirkt Lisette wie eine passende Sprache für Leute, die bestehende Go-Codebasen verbessern oder weiterhin die Go-Runtime nutzen möchten.
Was mir fehlt, ist ein Quickstart-Guide zur Frage: „Wie fange ich an, die folgende Datei statt in Go in Lisette zu schreiben?“
Zugehöriger Blogpost: Go is still not good
In Problemfeldern mit komplexen Referenzgraphen ist GC unverzichtbar, und dank Gos User-Mode-Stack-Struktur hat es ein effizientes Speichermodell.
Go eignet sich auch für solche schnell gebauten CLI-Tools — zum Beispiel: wordle-tui
Die Syntax ist einfach, es gibt Cross-Platform-Support, eingebaute Runtime und GC, das Modell „errors as values“, Green Threads, einen schnellen AOT-Compiler und mehr.
Gos
deferist nützlich, aber Fehlerbehandlung und Scope-Regeln wirken unbeholfen.TypeScript hat dieses Problem auch nicht gelöst, sondern eher verschlimmert. Deshalb habe ich selbst ein Option-Type-Paket gebaut und auf NPM veröffentlicht → fp-sdk
Es gibt bereits mehrere Sprachen, die nach Go kompilieren — XGo, Borgo, Soppo usw.
(T, error)einfach durch einen Result-Typ, aber semantisch ist das nicht völlig gleichwertig.Zum Beispiel bedeutet bei
io.Reader.Read(n!=0, io.EOF)ein normales Ende; wenn man das einfach als Fehler behandelt, führt das zu falschem Verhalten.Die Qualität der Fehlermeldungen von Lisette ist beeindruckend. Die „help“-Hinweise wirken tatsächlich nützlich.
Allerdings könnte der nach Go übersetzte Code sehr ausführlich werden, daher mache ich mir Sorgen, dass man bei Runtime-Fehlern im Go-Code debuggen muss.
Außerdem scheint die Richtung, aus bestehendem Go-Code heraus Lisette aufzurufen, schwierig zu sein.
Ich frage mich, ob Lisette eine experimentelle Sprache ist oder tatsächlich auf Produktion zielt.
lis run --debugwerden in den Go-Code//line source.lis:21:5-Kommentare eingefügt, sodass Stacktraces auf den ursprünglichen Lisette-Code gemappt werden.Das LSP behandelt Compile-Time-Fehler auf Basis der
.lis-Dateien.Aktuell gibt es noch keine Möglichkeit, Lisette aus Go aufzurufen, aber Go-Pakete aus Lisette zu importieren hat Priorität.
Anfangs war es ein Experiment, aber das Ziel ist, es zu einer produktionsreifen Sprache weiterzuentwickeln.
Ich frage mich, warum man die Rust-ähnliche Syntax nicht einfach vollständig übernommen hat.
Zum Beispiel
import "foo.bar"stattuse foo::bar,Bar.Baz =>stattBar::Baz =>usw.Wer Rust kennt, wird dadurch verwirrt, und wer es nicht kennt, kann Wissen nicht auf Rust übertragen.
intundfloat64folgen Gos Namenskonventionen für Typen.+einen.verwenden muss.Die Go-Runtime ist gut, aber die Sprache selbst wirkt grob und wenig verbesserungswillig.
Wenn man deshalb schon zu einem Transpiler greift, muss man Go vermutlich wirklich nicht mögen.
Ich frage mich, warum Rust und Rust-artige Sprachen Struct und Methode trennen.
Warum kann man Methoden nicht direkt im Struct definieren?
Außerdem können
impl-Blöcke andere Generic-Constraints haben als das Struct selbst, weshalb man mehrere davon definieren kann.Und schließlich ist Rust als Sprache darauf ausgelegt, vom Shape der Daten aus zu denken.
impl-Blöcke ähnlich anfühlen wie Methoden in Go; ich würde nicht sagen, dass das eine klar besser ist als das andere.Eine Sprache mit Python-ähnlicher Syntax, die aber nach Rust oder Go kompiliert, wäre wirklich großartig.
Lisette wirkt wie eine Sprache, die die Balance zwischen Gos Einfachheit und Rusts Komplexität gut trifft.
Ich frage mich, ob es einen Grund gibt, warum die Kompilierung viel langsamer als in Go sein sollte, und welche Rust-Features bewusst weggelassen wurden.
Zum Beispiel: Borrow Checking, Datentypen, async usw.
Go ist leicht zu lernen, aber funktional begrenzt.
Lisette wirkt interessant, weil es genau diese Lücken füllt.
So wie TypeScript JavaScript erweitert hat, könnte Go mit einem ausdrucksstarken Typsystem und einem strengen Compiler eine großartige Backend-Sprache werden.
Mein persönlicher Vorschlag wäre Unterstützung für Type-Sharing mit TypeScript-Frontends. Das ist einer der Gründe, warum TypeScript auch im Backend beliebt ist.
Als Entwickler für Infrastruktur-Automatisierung, der zwischen Rust-Sicherheit und Go-Einfachheit abwägt, finde ich die Idee, Rust-Bedienbarkeit auf die Go-Runtime zu setzen, äußerst attraktiv.
Ich werde die Weiterentwicklung des Projekts weiter beobachten.