Rendered at 17:14:48 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
thomashabets2 6 hours ago [-]
I'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.
> Basically, why try to make Go more like Rust when Rust is right there?
The avg developer moves a lot faster in a GC language. I recently tried making a chatbot in both Rust and Python, and even with some experience in Rust I was much faster in Python.
No doubt a chatbot would be built faster if using a less strict language. It wasn't until I started working on larger Python codebases (written by good programmers) that I went "oh no, now I see how this is not an appropriate language".
Similar to how even smaller problems are better suited for just writing a bash script.
When you can have the whole program basically in your head, you don't need the guardrails that prevent problems. Similar to how it's easy to keep track of object ownership with pointers in a small and simple C program. There's no fixed size after which you can no longer say "there are no dangling pointers in this C program". (but it's probably smaller than the size where Python becomes a problem)
My experience writing TUI in Go and Rust has been much better in Rust. Though to be fair, the Go TUI libraries may have improved a lot by now, since my Go TUI experience is older than me playing with Rust's ratatui.
aaztehcy 7 minutes ago [-]
[dead]
zozbot234 2 hours ago [-]
> moves a lot faster in a GC language
Only in the old "move fast and break things" sense. RAII augmented with modern borrow checking is not really any syntactically heavier than GC, and the underlying semantics of memory allocations and lifecycles is something that you need to be aware of for good design. There are some exceptions (problems that must be modeled with general reference graphs, where the "lifecycle" becomes indeterminate and GC is thus essential) but they'll be quite clear anyway.
wavemode 1 hours ago [-]
> Only in the old "move fast and break things" sense
No, definitely not only in that sense. GC is a boon to productivity no matter how you slice it, for projects of all sizes.
I think the idea that this is not the case, perhaps stems from the fact that Rust specifically has a better type system than Java specifically, so that becomes the default comparison. But not every GC language is Java. They don't all have lax type systems where you have to tiptoe around nulls. Many are quite strict and are definitely not "move fast and break things" type if languages.
thomashabets2 33 minutes ago [-]
Well if you think Java doesn't have a sufficiently good type system, then surely Go is even further from one?
Not saying those are the only two GC languages, just circling back to the post spawning these comments.
8 minutes ago [-]
zozbot234 5 hours ago [-]
> Basically, why try to make Go more like Rust when Rust is right there?
Go gives you access to a compute- and memory-efficient concurrent GC that has few or no equivalents elsewhere. It's a great platform for problem domains where GC is truly essential (fiddling with spaghetti-like reference graphs), even though you're giving up the enormous C-FFI ecosystem (unless you use Cgo, which is not really Go in a sense) due to the incompatibilities introduced by Go's weird user-mode stackful fibers approach.
knocte 4 hours ago [-]
From your blog entry:
> Go was not satisfied with one billion dollar mistake, so they decided to have two flavors of NULL
Thanks for raising this kind of things in such a comprehensible way.
Now what I don't understand is that TypeScript, even if it was something to make JavaScript more bearable, didn't fix this! TS is even worse in this regard. And yet no one seems to care in the NodeJS ecosystem.
<selfPromotion>That's why I created my own Option type package in NPM in case it's useful for anyone: https://www.npmjs.com/package/fp-sdk </selfPromotion>
alpinisme 3 hours ago [-]
Your readme would really benefit from code snippets illustrating the library. The context it currently contains is valuable but it’s more what I’d expect at the bottom of the readme as something more like historical context for why you wrote it.
knocte 3 hours ago [-]
Yup, in my TODO list (I've only recently published this package). For now you can just check the tests, or a SO answer I wrote a while ago (before I published the idea as an npm package): https://stackoverflow.com/a/78937127/544947
symaxian 2 hours ago [-]
You can enable null safety in TypeScript, seems like a pretty good fix to me.
knocte 1 hours ago [-]
Where did we lose you? we're talking about two flavours of null, not one.
euroderf 1 hours ago [-]
"A typed nil pointer is not a nil pointer."
smt88 3 hours ago [-]
How would TS fix null in JS without violating its core principles of adhering to EcmaScript standards and being a superset of JS?
knocte 3 hours ago [-]
Maybe spit warnings when undefined is used? In the same way it does for when you use typeScript in a type-loose way.
But yeah it's a fair point. Sometimes I think I should just write my own lang (a subset of typescript), in the same fashion that Lisette dev has done.
smw 5 hours ago [-]
Rust'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 4 hours ago [-]
Does 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.
Matl 3 hours ago [-]
For one, I am glad I don't have to color my functions like your typical async.
thomashabets2 31 minutes ago [-]
I agree that this is the big problem with Rust's async story.
But like I said, in my opinion this compares with Go not having an async story at all.
osigurdson 2 hours ago [-]
Go's async story is great, as there is no function coloring at all. That being said, I don't like Go's syntax very much. The runtime is great though.
Both 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.
ivov_dev 2 hours ago [-]
You are right, and thank you for pointing this out. I've opened an issue:
I have a few approaches in mind and will be addressing this soon.
amelius 8 hours ago [-]
How do compile errors propagate back from the target language to the source language?
usrnm 8 hours ago [-]
They are not supposed to produce code that doesn't compile, why would they?
debugnik 7 hours ago [-]
Debugger positions on the other hand are a pain with these things.
amelius 5 hours ago [-]
Uh yes, that's what I meant ;)
In C/C++ you have the #line preprocessor directive. It would be nice if Go had something similar.
debugnik 41 minutes ago [-]
Go has apparently got //line directives, and this project uses them.
virtualritz 8 hours ago [-]
Looks 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
8organicbits 5 hours ago [-]
I switch between languages a lot and I'm currently learning PHP. I've found that syntax similarities can be a hazard. I see "function" and I think I'm writing JavaScript, but then I try to concatenate strings with "+" and I realize I'm actually writing PHP and need to use ".". These challenges are especially noticeable in the early days of learning.
sheept 7 hours ago [-]
These 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 6 hours ago [-]
> It's similar to how Rust has isize but no fsize.
isize is the type for signed memory offsets, fsize is completely nonsensical.
5 hours ago [-]
apatheticonion 6 hours ago [-]
Same. I started writing a high level Rust that was based on typescript.
Then realized Rust wasn't that hard.
zozbot234 4 hours ago [-]
Writing actual Rust for any GC language (including Golang) would ultimately be quite weird. You'd have to entirely change the way memory is modeled, to account for the restrictions GC introduces. It's similar to the restrictions introduced by having multiple address spaces, except even weirder because every object is its own tiny address space and a reference is just an address space descriptor.
thrance 7 hours ago [-]
I 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.
troupo 5 hours ago [-]
Because it's inspired by Rust, but doesn't try to be Rust? And it's aimed at Go developers?
osigurdson 2 hours ago [-]
I'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.
emanuele-em 10 hours ago [-]
Really 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 4 hours ago [-]
Thanks 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 1 hours ago [-]
I 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 18 minutes ago [-]
Thanks 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.
lucianmarin 8 hours ago [-]
A programming language similar to Python that compiles to Rust or Go will be amazing.
Hold up... did I miss something, is Mojo open sourced now?
Edit: No it is still not open source. There are still same promises of open sourcing eventually, but there is no source despite the URL and the website claiming it's an open language. What's "open" here is "MAX AI kernels", not Mojo. They refer to this as "750k lines of open source code" https://github.com/modular/modular/tree/main/max/kernels
This feels icky to me.
Hasnep 8 hours ago [-]
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
debo_ 3 hours ago [-]
Nim looks a lot like Python with a first-class type system and compiles to many different targets, including wasm and C.
F# is very similar to python because it's based on indentation instead of curly braces. And with Fable you can transpile it to Rust (or Python even): https://github.com/fable-compiler/fable
I'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 7 hours ago [-]
Having 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 6 hours ago [-]
That 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 6 hours 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.
jasdfwasd 4 hours ago [-]
Could large data types be problematic for the prelude types Option/Result/Tuple? They don't store as pointer and every receiver is by value.
smokel 5 hours ago [-]
This 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 3 hours ago [-]
Horrible 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.
sail0rm00n 9 hours ago [-]
I’m sold just for proper enumeration support.
oncallthrow 5 hours ago [-]
I'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 5 hours ago [-]
The first example suggests yes.
OJFord 5 hours ago [-]
Really? Almost every example imports something from Go, and it states "interoperability with the Go ecosystem" (or similar, from memory).
oncallthrow 5 hours ago [-]
That isn’t the same thing. Indeed, upon reading further, it appears there is no way to import non-stdlib go modules.
ivov_dev 4 hours ago [-]
Support 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.
Well that's why I decided to go C# for general purpose stuff
seabrookmx 1 minutes ago [-]
Ditto. 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).
phplovesong 10 hours ago [-]
Go 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.
ksec 7 hours ago [-]
On 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 3 hours ago [-]
Because it offers things where Go today doesn’t and never will?
bestouff 9 hours ago [-]
For "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 9 hours ago [-]
In 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 :)
mirekrusin 7 hours ago [-]
MoonBit [0] is the best/future complete/active “rust with gc”.
Did MoonBit add support for some kind of shared memory concurrency like threads? I remember discovering the language, being very excited about it, and then learning it is single-threaded, which makes it a poor replacement for Rust IMHO.
akkad33 8 hours ago [-]
You can use Ocaml today and achieve all the correctness
masklinn 6 hours ago [-]
> all the correctness
When did OCaml get affine types? Or unique references?
OCaml has a lot of other cons though that Rust doesn't have. I would definitely pick Rust over OCaml even for projects that can tolerate a runtime with GC pauses. (And clearly most people agree.)
amelius 8 hours ago [-]
What cons?
jech 5 hours ago [-]
The ecosystem. The language is lovely, but dune/opam is not up to the standard of the Go or Rust build systems, and the set of useful libraries is somewhat skewed. Whenever I write a program in Caml, I gain an hour thanks to the nice language, and then lose two fighting with dune/opam.
There's also the support for concurrency and parallelism, which has started to improve recently, but is still years behind what is available in Go (but still better in my opinion than what is available in Rust).
zorobo 7 hours ago [-]
For example, multicore OCaml is not free of race conditions.
The GC, while super efficient (pauses are in the milliseconds), is not suitable for hard realtime.
Still, where absolute max performance or realtime are not required, I'd choose OCaml as it is elegant & a pleasure to code in (personal opinion, ymmv).
IshKebab 5 hours ago [-]
Poor windows support, confusing and buggy tooling (yeah really), mediocre documentation, global type inference, weird obsession with linked lists leading to performance gotchas, difficult syntax (yeah really), small community.
I can expand on any of those if you disagree with them.
gf000 9 hours ago [-]
There 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 8 hours ago [-]
I 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.
masklinn 6 hours ago [-]
> Yes, it's also a systems language without a runtime. But that's not the novel part.
Low level strong correctness was absolutely a novel part. In fact it’s exactly why many people glommed onto early rust, and why it was lowered on the stack.
Although learnability and weirdness budgets were also extremely novel in low level contexts which had been subsumed by C and C++.
> horrors in C++
Yes, horrors in C++. Half baked jerry-rigged and barely usable nonsense. Not an industrial strength langage with a reliable type system and a strong focus on safety through types.
uecker 4 hours ago [-]
Memory safety is not the same a scorrectness and more advanced type is also not the same thing as correctness.
masklinn 3 hours ago [-]
50 years of computing have proved pretty conclusively that less than that is wishful thinking at best. Large C++ programs, even with massive amounts of resources and tooling, can’t even get memory management correct.
uecker 2 hours ago [-]
That Rust gives you correctness is very misleading claim.
gf000 5 hours ago [-]
These are all great qualities of rust, but they would not have been enough to make a dent.
Being memory safe without being managed is what makes rust a truly novel and interesting language for which it rightfully gets the hype.
furyofantares 7 hours ago [-]
It looks like more of a Rust-y way to write Go rather than a Go-ish way to run Rust. So I think the question is more about if you would choose it for something you're choosing Go for today, rather than for something you're choosing Rust for today.
Imustaskforhelp 8 hours ago [-]
No, this is actually nice to be honest. It's not a step backwards imo.
if I can incorporate Lisette into my golang projects for example, (Invoking rust code within Golang to me feels like a larger problem and Invoking C might be easier from my tinkering experiments) I feel like you are viewing this from a pure performance metric but to be honest, most things aren't necessary to be the fastest, the type system of rust/rust-alike languages can be beneficial to people as-it-is
Check out gleam, its based on erlang so it has a runtime involved, people love gleam because it gives them a bit more expressiveness in the type system from what I've heard.
I feel like these experiments are genuinely nice, Also perhaps a project like this can then slowly also invoke tinyGo (there was a recent discussion about it too) and could be compiled into tinyGo in future iterations to have no runtime essentially as well. People who love rust, love it, but most people really find it hard to get-into as compared to golang, I really love golang for its simplicity but I wish to tinker with rust too, so if Lisette combines both of these things and atleast makes me familiar with more rust without having to jump into too many hoops
GandalfHN 29 minutes ago [-]
[dead]
rbbydotdev 7 hours ago [-]
Looks beautiful! Any plans to make it self compile?
bhwoo48 7 hours ago [-]
Love 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
tempaccount420 5 hours ago [-]
Please commit your CLAUDE.md
kubb 8 hours ago [-]
Oh look, a better syntax than the Go team could design!
Comma2976 7 hours ago [-]
Nuh uh
emehex 6 hours ago [-]
Looks a lot like Swift! Awesome!
bluebarbet 5 hours ago [-]
Eats shoots and leaves.
rednafi 7 hours ago [-]
Go 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 :)
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
The avg developer moves a lot faster in a GC language. I recently tried making a chatbot in both Rust and Python, and even with some experience in Rust I was much faster in Python.
Go is also great for making quick lil CLI things like this https://github.com/sa-/wordle-tui
Similar to how even smaller problems are better suited for just writing a bash script.
When you can have the whole program basically in your head, you don't need the guardrails that prevent problems. Similar to how it's easy to keep track of object ownership with pointers in a small and simple C program. There's no fixed size after which you can no longer say "there are no dangling pointers in this C program". (but it's probably smaller than the size where Python becomes a problem)
My experience writing TUI in Go and Rust has been much better in Rust. Though to be fair, the Go TUI libraries may have improved a lot by now, since my Go TUI experience is older than me playing with Rust's ratatui.
Only in the old "move fast and break things" sense. RAII augmented with modern borrow checking is not really any syntactically heavier than GC, and the underlying semantics of memory allocations and lifecycles is something that you need to be aware of for good design. There are some exceptions (problems that must be modeled with general reference graphs, where the "lifecycle" becomes indeterminate and GC is thus essential) but they'll be quite clear anyway.
No, definitely not only in that sense. GC is a boon to productivity no matter how you slice it, for projects of all sizes.
I think the idea that this is not the case, perhaps stems from the fact that Rust specifically has a better type system than Java specifically, so that becomes the default comparison. But not every GC language is Java. They don't all have lax type systems where you have to tiptoe around nulls. Many are quite strict and are definitely not "move fast and break things" type if languages.
Not saying those are the only two GC languages, just circling back to the post spawning these comments.
Go gives you access to a compute- and memory-efficient concurrent GC that has few or no equivalents elsewhere. It's a great platform for problem domains where GC is truly essential (fiddling with spaghetti-like reference graphs), even though you're giving up the enormous C-FFI ecosystem (unless you use Cgo, which is not really Go in a sense) due to the incompatibilities introduced by Go's weird user-mode stackful fibers approach.
> Go was not satisfied with one billion dollar mistake, so they decided to have two flavors of NULL
Thanks for raising this kind of things in such a comprehensible way.
Now what I don't understand is that TypeScript, even if it was something to make JavaScript more bearable, didn't fix this! TS is even worse in this regard. And yet no one seems to care in the NodeJS ecosystem.
<selfPromotion>That's why I created my own Option type package in NPM in case it's useful for anyone: https://www.npmjs.com/package/fp-sdk </selfPromotion>
But yeah it's a fair point. Sometimes I think I should just write my own lang (a subset of typescript), in the same fashion that Lisette dev has done.
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.
But like I said, in my opinion this compares with Go not having an async story at all.
https://github.com/ivov/lisette/issues/12
I have a few approaches in mind and will be addressing this soon.
In C/C++ you have the #line preprocessor directive. It would be nice if Go had something similar.
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
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.
isize is the type for signed memory offsets, fsize is completely nonsensical.
Then realized Rust wasn't that hard.
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.
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.
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)?
Edit: No it is still not open source. There are still same promises of open sourcing eventually, but there is no source despite the URL and the website claiming it's an open language. What's "open" here is "MAX AI kernels", not Mojo. They refer to this as "750k lines of open source code" https://github.com/modular/modular/tree/main/max/kernels
This feels icky to me.
https://github.com/py2many/static-python-skill
Last commit was 9 years ago though, so targets Python 2.7.
†: 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).
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.
Not sure I'd like the constant reminder.
[1] https://github.com/ivov/lisette/blob/main/tools/bindgen/READ...
Lisette brings you the best of both worlds.
I know it is Rust inspired, but why write it in Rust and not Go?
What would be actually nice is running async Rust on the Go green threads runtime.
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 :)
[0] https://www.moonbitlang.com
When did OCaml get affine types? Or unique references?
There's also the support for concurrency and parallelism, which has started to improve recently, but is still years behind what is available in Go (but still better in my opinion than what is available in Rust).
Still, where absolute max performance or realtime are not required, I'd choose OCaml as it is elegant & a pleasure to code in (personal opinion, ymmv).
I can expand on any of those if you disagree with them.
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.
Low level strong correctness was absolutely a novel part. In fact it’s exactly why many people glommed onto early rust, and why it was lowered on the stack.
Although learnability and weirdness budgets were also extremely novel in low level contexts which had been subsumed by C and C++.
> horrors in C++
Yes, horrors in C++. Half baked jerry-rigged and barely usable nonsense. Not an industrial strength langage with a reliable type system and a strong focus on safety through types.
Being memory safe without being managed is what makes rust a truly novel and interesting language for which it rightfully gets the hype.
if I can incorporate Lisette into my golang projects for example, (Invoking rust code within Golang to me feels like a larger problem and Invoking C might be easier from my tinkering experiments) I feel like you are viewing this from a pure performance metric but to be honest, most things aren't necessary to be the fastest, the type system of rust/rust-alike languages can be beneficial to people as-it-is
Check out gleam, its based on erlang so it has a runtime involved, people love gleam because it gives them a bit more expressiveness in the type system from what I've heard.
I feel like these experiments are genuinely nice, Also perhaps a project like this can then slowly also invoke tinyGo (there was a recent discussion about it too) and could be compiled into tinyGo in future iterations to have no runtime essentially as well. People who love rust, love it, but most people really find it hard to get-into as compared to golang, I really love golang for its simplicity but I wish to tinker with rust too, so if Lisette combines both of these things and atleast makes me familiar with more rust without having to jump into too many hoops
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 :)