7 ms·
Lisette a little language inspired by Rust that compiles to Go
- phplovesong 6mo agoGo has an awesome runtime, but at the same time has a very limited typesystem, and is missing features like exhaustive pattern matching, adts and uninitted values in structs. Lisette brings you the best of both worlds.
- emanuele-em 6mo agoReally nice work on this. The error messages alone show a lot of care, the "help" hints feel genuinely useful, not just compiler noise. I'm curious about the compiled Go output though. The Result desugaring gets pretty verbose, which is totally fine for generated code, but when something breaks at runtime you're probably reading Go, not Lisette. Does the LSP handle mapping errors back to source positions? Also wondering about calling Lisette from existing Go code (not just the other direction). That feels like the hard part for adoption in a mixed codebase. Is the goal here to eventually be production-ready or is it more of a language design exploration? Either way it's a cool project.
- ivov_dev 6mo agoThanks for your kind words :) The CLI command `lis run` supports a `--debug` flag to insert `//line source.lis:21:5` directives into the generated Go, so stack traces from runtime errors point back to the original Lisette source positions. The LSP handles compile-time errors, which reference `.lis` files by definition. Calling Lisette from existing Go is not yet supported and is the harder direction, as you noted. This is on my mind, but the more immediate priority is enabling users to import any Go third-party package from Lisette. Lisette began as an exploration, but I intend to make it production-ready.
- ModernMech 6mo agoI noticed the project is less than a month old, and you've generated over 300k lines of code here. I'm guessing most of this was written by agents, yes? I'm asking because your goal is to make it production ready, so what are you doing to assure people this is more than just another vibe coded language (of which there are countless examples by now)?
- ivov_dev 6mo agoThanks for asking! The core of the compiler should be close to 50k LoC, with most of the rest being tests. The project is much older than git history suggests - I started a fresh repository for the initial release after several months of experiments and false starts to find the right direction. LLMs certainly helped e.g. with mechanical tasks like generating tests and refactors where changes cascaded throughout the pipeline, and I also relied on them to understand Hindley-Milner type inference, Lindig for the formatter, and Maranget for exhaustiveness checking.
- ModernMech 6mo agoThanks for the response but I'm sorry to say it's not reassuring, but does more to worry me because you didn't answer the question. Like I said, these LLM-driven language projects have proliferated recently, and they follow a common pattern: - Dump hundreds of thousands of lines of lines into a blank repo with a new repo. - Throw up a polished-looking LLM generated website (they all look the same). - Post about the project on a bunch of tech sites like HN. - Claim it's a real project with deep roots despite there being no evidence. Here's another one: https://www.reddit.com/r/ProgrammingLanguages/comments/1sa1a34/been_making_a_language_called_xs_feedback_pt_2/ https://www.reddit.com/r/ProgrammingLanguages/comments/1sa1a... These things are so common that r/programminglanguages had to ban them, because they were being posted constantly. So my concern is: what differentiates your project from the sea of others exactly like it, which as I've been following them? Usually the main dev grows bored with it quickly when the agent starts having trouble building features and the project is silently abandoned.
- rattray 6mo agoAbandoned open-source projects with poor code quality are nothing new. The merits of any project are yours to evaluate. To me, I see some encouraging thoughtfulness here. However, again, it's true most projects like this don't achieve liftoff.
- sail0rm00n 6mo agoI’m sold just for proper enumeration support.
- bestouff 6mo agoFor "classic" Rust what's actually nice is that no runtime is needed, so this looks like a step backwards. What would be actually nice is running async Rust on the Go green threads runtime.
- andai 6mo agoIn my experience, what's actually nice is the correctness. The low-levelness is not helpful for most of the software I write, and imposes a constant burden. Rust, of course superbly achieves its goals within its niche! But it is a niche, is my meaning here. What I actually want is code that's correct, but ergonomic to write. So my ideal language (as strange as it sounds) would be Rust with a GC. I don't want to worry about what string type I'm using. I want it to just work. But I want it to work correctly. Lisette looks like it's in this exact category! It seems to combine the best aspects of both Rust and Go, which is a very promising endeavour. I'll have to take a proper look :)
- gf000 6mo agoThere are an endless number of modern MLs that do the same thing. That's not a novelty - Rust was novel in making it part of a low-level language.
- tux3 6mo agoI don't think being low level is the main innovation, really. There are several things Rust did right over traditional ML. Explicitly caring about learnability and the "weirdness budget". Having great error messages that don't require a course in category theory (many ML) or 800kB of scrollback buffer (C++) to understand. Having great tools. Excellent documentation. Being friendly to new users. Yes, it's also a systems language without a runtime. But that's not the novel part. You could write horrors in C++ that approximate ML even without language support. There are eldritch libraries where some kind of pattern matching is done via generic lambdas. The main difference is developper UX. Good tools, good error messages, quality of life. The novelty is making ML not painful.
- baranul 6mo agoThere are several languages that compile to Go, trying to be a better a Go. Off the top of my head: XGo (https://github.com/goplus https://github.com/goplus), Borgo (https://github.com/borgo-lang/borgo https://github.com/borgo-lang/borgo), Soppo (https://github.com/halcyonnouveau/soppo https://github.com/halcyonnouveau/soppo)...
- amelius 6mo agoHow do compile errors propagate back from the target language to the source language?
- kbolino 6mo agoBoth Borgo and now Lisette seem to act as though (T, error) returns are equivalent to a Result<T, error> sum type, but this is not semantically valid in all cases. The io.Reader interface's Read method, for example, specifies not only that (n!=0, io.EOF) is a valid return pattern, but moreover that it is not even an error condition, just a terminal condition. If you treat the two return values as mutually exclusive, you either can't see that you're supposed to stop reading, or you can't see that some number of valid bytes were placed into the buffer. This is probably well known enough to be handled specifically, but other libraries have been known to make creative use of the non-exclusivity in multiple return values too.
- virtualritz 6mo agoLooks great. But I can't help wondering: If it is similar to Rust why not make it the the same as Rust where it feature-matches? Why import "foo.bar" instead of use foo::bar? Why Bar.Baz => instead of Bar::Baz =>? What are you achieving here? Why make it subtlety different so someone who knows Rust has to learn yet another language? And someone who doesn't know Rust learns a language that is different enough that the knowledge doesn't transfer to writing Rust 1:1/naturally? Also: int but float64? Edit: typos
- thrance 6mo agoI think "Because (the dev) prefers it that way" is a satisfactory answer. Often, these small languages don't aim to be used in production and become the next big thing. They're made for fun and exploration's sake.
- sheept 6mo agoThese are just syntax differences, which not only are easy to learn but I believe aren't the primary goal of the language, which is to bring the benefits of Rust's type system to Go. As for int and float64, this comes from Go's number type names. There's int, int64, and float64, but no float. It's similar to how Rust has isize but no fsize.
- masklinn 6mo ago> It's similar to how Rust has isize but no fsize. isize is the type for signed memory offsets, fsize is completely nonsensical.
- deleted 6mo ago[deleted]
- apatheticonion 6mo agoSame. I started writing a high level Rust that was based on typescript. Then realized Rust wasn't that hard.
- 6mo ago
- lucianmarin 6mo agoA programming language similar to Python that compiles to Rust or Go will be amazing.
- amelius 6mo agoWhat benefit would it bring? There's already https://cython.org/ https://cython.org/
- mememememememo 6mo agoYou want to use the Go runtime for example
- adsharma 6mo agoCython uses C-API. This one doesn't.
- Hasnep 6mo agoSpy (https://github.com/spylang/spy https://github.com/spylang/spy) is an early version of this kind of thing. I believe it compiles to C though, kinda like Nim. Actually speaking of Nim, that's probably the most mature language in this space, although it's less pythonic than Spy
- emmelaich 6mo agoHere you are. https://github.com/google/grumpy https://github.com/google/grumpy Last commit was 9 years ago though, so targets Python 2.7.
- adsharma 6mo agoAmazing people still keep discovering it. And google search fails to surface working implementations. "Python to rust transpiler" -> pyrs (py2many is a successor) "Python to go transpiler" -> pytago Grumpy was written around a time when people thought golang would replace python. Google stopped supporting it a decade ago. Even the 2022 project by a high school student got more SEO https://github.com/py2many/py2many/issues/518 https://github.com/py2many/py2many/issues/518
- kubb 6mo agoOh look, a better syntax than the Go team could design!
- Comma2976 6mo agoNuh uh
- weiyong1024 6mo ago[flagged]
- melodyogonna 6mo agoI'm wondering about the logistics of making this integrate with Go at the assembly/object file level rather than at source code level. What if it compiled to Go's assembly rather than to Go source code
- darccio 6mo agoHaving explored that approach (†), I can tell that generating Go assembly is harder than it seems. †: I've tried to transpile Rust code through WASM into Go assembly, and I've also explored how to inject trampolines into Go binaries (which involves generating Go assembly too).
- melodyogonna 6mo agoThat is interesting, but I imagine Rust has features which can not be translated into Go's assembly. This language is specifically designed for Go interop; the logistics wouldn't be the same, though I still expect it to be difficult.
- masklinn 6mo ago> I imagine Rust has features which can not be translated into Go's assembly Why would there be? Go’s assembly might be lacking ways to make them optimally efficient, but that’s probably a given either way without an optimizing compiler backend.
- rbbydotdev 6mo agoLooks beautiful! Any plans to make it self compile?
- rednafi 6mo agoGo syntax and the Go runtime would be the perfect combo for me. Oh well... I love Rust for what it is, but for most of my projects, I can’t justify the added complexity. Sure, there are a bunch of things I miss from the Rust world when I’m working on large-scale distsys services in Go, but introducing Rust in that space would be a recipe for disaster. I guess the Go team knows that if they start adding everyone’s favorite Rust features, the language would become unrecognizable. So we’re not getting terser error-handling syntax or enums. Having union types would be nice too. But I work in platform engineering, so my needs are quite different from someone writing business logic in Go. I understand that having a more expressive syntax is nice when you’re writing complex business code, but in reality, that almost always comes with a complexity/fragility tradeoff. That’s part of the reason no one wants to use Rust to write their business logic, despite it being so much more expressive. For distsys, programming ergonomics matter far less compared to robustness and introspectability. So the Go runtime with Go syntax is perfect for this. But of course, that’s not true for all use cases. Sorry for the rant - completely uncalled for. This is a cool project nonetheless :)
- phplovesong 6mo agoAre you a bot?
- rednafi 6mo agoNah made the same comment on r/golang
- bhwoo48 6mo agoLove the idea of bringing Rust ergonomics to the Go runtime. As someone currently building infra-automation tools (Dockit), the trade-off between Rust's safety and Go's simplicity is always a hot topic. This project addresses it in a very cool way. Will definitely follow the development
- ksec 6mo agoOn the surface this looks great. Seems to hit the sweet spot in a lot of areas. I know it is Rust inspired, but why write it in Rust and not Go?
- metaltyphoon 6mo agoBecause it offers things where Go today doesn’t and never will?
- emehex 6mo agoLooks a lot like Swift! Awesome!
- thomashabets2 6mo agoI've chatted a bit with the author, but not actually tried the language. It looks very interesting, and a clear improvement. I'm not particularly quiet about not liking Go[1]. I do think there may be a limit to how far it can be improved, though. Like typed nil means that a variable of an interface type (say coming from pure Go code) should enter Lisette as Option<Option<http.Handler>>. Sure, one can match on Some(Some(h)) to not require two unwrapping steps, but it becomes a bit awkward anyway. (note: this double-Option is not a thing in Lisette at least as of now) Lisette also doesn't remove the need to call defer (as opposed to RAII) in the very awkward way Go does. E.g. de facto requiring that you double-close on any file opened for write. Typescript helps write javascript, but that's because until WASM there was no other language option to actually run in the browser. So even typescript would be a harder sell now that WASM can do it. Basically, why try to make Go more like Rust when Rust is right there? And fair enough, the author may be aiming for somewhere in between. And then there's the issue of existing codebases; not everything is greenfield. So this seems best suited for existing Go codebases, or when one (for some reason) wants to use the Go runtime (which sure, it's at least nicer than the Java runtime), but with a better language. And it does look like a better language. So I guess what's not obvious to me (and I mentioned this to the author) is what's the quick start guide to having the next file be in Lisette and not Go. I don't think this is a flaw, but just a matter of filling in some blanks. [1] https://blog.habets.se/2025/07/Go-is-still-not-good.html https://blog.habets.se/2025/07/Go-is-still-not-good.html
- smw 6mo agoRust's async story is much less ergonomic than go's -- mostly because of lack of garbage collection. That might be a good reason by itself?
- thomashabets2 6mo agoDoes Go actually have an async story? I know that question risks starting a semantic debate, so let me be more specific. Go allows creating lightweight threads to the point where it's a good pattern to just spin off goroutines left and right to your heart's content. That's more of a concurrency primitive than async. Sure, you combine it with a channel, and you've created an async future. The explicit passing of contexts is interesting. I initially thought it would be awkward, but it works well in practice. Except of course when you need to call a blocking API that doesn't take context. And in environments where you can run a multitasking runtime, that's pretty cool. Rust's async is more ambitious, but has its drawbacks. Go's concurrency story (I wouldn't call it an async story) is way more yolo, as is the rest of the Go language. And in my experience that Go yolo tends to blow up in more hilarious ways once the system is complex enough.
- oncallthrow 6mo agoI've read the entire page and still don't know whether or not I can import Go modules in this language, which seems rather important
- 0x696C6961 6mo agoThe first example suggests yes.
- OJFord 6mo agoReally? Almost every example imports something from Go, and it states "interoperability with the Go ecosystem" (or similar, from memory).
- oncallthrow 6mo agoThat isn’t the same thing. Indeed, upon reading further, it appears there is no way to import non-stdlib go modules.
- ivov_dev 6mo agoSupport for Go third-party packages is not part of this first release, but the tooling to generate bindings for Go packages (which enables imports from the Go stdlib) is already in place[1]. Extending it to support third-party packages is on the roadmap. [1] https://github.com/ivov/lisette/blob/main/tools/bindgen/README.md https://github.com/ivov/lisette/blob/main/tools/bindgen/READ...
- bluebarbet 6mo agoEats shoots and leaves.
- KaiLetov 6mo ago[dead]
- smokel 6mo agoThis is great news for those of us looking for baby names. So far my list includes: Pascal, Ada, Dylan, Crystal, Lisa, Julia, Ruby, and now Lisette.
- Kaliboy 6mo agoHorrible news for me, I quite like the idea and syntax, but it also reminds me of my wife which I am currently divorcing. Not sure I'd like the constant reminder.
- tempaccount420 6mo agoPlease commit your CLAUDE.md
- jasdfwasd 6mo agoCould large data types be problematic for the prelude types Option/Result/Tuple? They don't store as pointer and every receiver is by value.
- stevefan1999 6mo agoWell that's why I decided to go C# for general purpose stuff
- seabrookmx 6mo agoDitto. C# gets a bad rap due to its Windows-exclusive history, but it's now cross platform and has most of the features PL nerds are looking for. Strict nulls, pattern matching, a really mature and easy to use async ecosystem (it invented async/await), even a lot of the low level stuff is there (unsafe{} blocks ala rust and manual memory management where needed).
- simonask 6mo agoC# is nice, but it is nowhere near Rust in terms of safety or expressiveness. Thankfully they are finally adding discriminated unions (sum types) and other sorely missing features. Unsafe in C# is much more dangerous than unsafe in Rust, precisely because it doesn’t actually color a function. It just allows its body to use pointers. This is why you have methods in the CLR called “DangerousFoo()”, and the compiler does nothing to prevent you from calling them.
- seabrookmx 6mo agoRust also has a much steeper learning curve. I can onboard an average developer that's familiar with Typescript and have them be productive in C# in a week. This one is more subjective, but I also think C# has a more mature and painless web stack. I love both languages but for me they each fill a different role.
- simonask 6mo agoI think this just says that TypeScript and C# are more similar languages than either is to Rust, which I would agree with. Rust's learning curve is not steep at all if you're coming from C or C++. C# also has a pretty steep learning curve if you have to care about the things where Rust excels, like correctness or maximum efficiency (which typically does not include web stuff). I would even say that Rust is the easiest language in which to approach that level of correctness and efficiency.
- osigurdson 6mo agoI'd always liked the Go runtime but the language is pretty clunky imo and I don't think they will ever improve it (because they don't think anything is wrong with it). However, you have to really dislike the language to use a transpiler.
- Defletter 6mo agoSomething that I don't understand about Rust, or these rustylangs, is the insistence of separating structs and methods. Don't get me wrong, I like named-impl blocks, but why are they the only option? Why can't I put an unnamed-impl block inside the struct? Or better yet just define methods on the struct? What's the point of this and why do these rustylangs never seem to change this?
- phplovesong 6mo agoDunno. Impl block are very similar to Go methods. I dont think one if better than the other.
- deleted 6mo ago[deleted]
- simonask 6mo agoThere are several reasons. 1. Struct fields are really important in Rust because of auto-traits. Your life as a Rust programmer is easier if all fields fit on the screen, because one of them may be the reason your struct is `!Sync` or whatever. 2. Impl blocks can have different generic bounds from the struct itself, which is a nice shorthand for repeating the same generic bounds for a series of related methods. So you need to be able to write multiple per type anyway. It would he confusing if there was an “implied” impl block to look for as well. 3. It helps emphasize that Rust is a language that wants you to think about the shape of your data.
- Defletter 6mo agoThese don't seem like insurmountable challenges though. Unnamed impl blocks could work entirely within requirements. There could also be a lint to warn about any fields that are below trait definitions. struct Example { number: i32, } impl Example { fn boo() { println!("boo! Example::boo() was called!"); } } trait Thingy { fn do_thingy(&self); } impl Thingy for Example { fn do_thingy(&self) { println!("doing a thing! also, number is {}!", self.number); } } This could be expressed as: struct Example { number: i32, impl { fn boo() { println!("boo! Example::boo() was called!"); } } impl Thingy { fn do_thingy(&self) { println!("doing a thing! also, number is {}!", self.number); } } } trait Thingy { fn do_thingy(&self); } Keeping related things together is just infinitely more readable, in my opinion. In fact, the confusing nature of "impl <struct>" becoming "impl <trait> for <struct>" is obviated by internal impl blocks. Keeping them separate just seems so artificial, if not downright dogmatic.
- rattray 6mo agoThis seems awesome. Seems to address many of my armchair complaints about both Go (inexpensive) and Rust (bloated/complex). I'm curious what compilation times are like? Are there theoretical reasons it'd be order of magnitude slower than Go? I assume it does much less than the rust compiler... Relatedly, I'd be curious to see some of the things from Rust this doesn't include, ideally in the docs. Eg I assume borrow checking, various data types, maybe async etc are intentionally omitted?
- Surac 6mo agoborrowing syntax from rust is not what i like to read. Reading Rust code always gives me VisualBasic vibes. In VB you also declare variables like: dim a as Integer. and use let a=a+1
- darkest_ruby 6mo agoThis is what go should have been, instead of a mess it is today
- onlyjanand 6mo ago[dead]
- gethly 6mo agoGo is epitome of simplicity. Why on earth would you want to put another abstraction on top of it? There is Solod project that is Go subset that compiles into C that is more interesting https://github.com/solod-dev/solod https://github.com/solod-dev/solod
- n_u 6mo agoThis is really cool! Go is so dead simple to learn but it just lacks a few features. I feel this really fills that specific gap. Go with more expressive types and a bit stricter compiler to prevent footguns would be a killer backend language. Similar to what TypeScript was to JavaScript. My 2 cents would be to make it work well with TypeScript frontends. I think TypeScript is so popular in backends because 1. you can share types between frontend code and backend code and 2. it's easy for frontend devs to make changes to backend code.