NOW LET US – AI RAG SaaS Studio TP.HCM
NOW LET US
Digital Product Studio
Back to news
DEV-TOOLS...4 min read

Lisette: A little language inspired by Rust that compiles to Go

Share
NOW LET US Article – Lisette: A little language inspired by Rust that compiles to Go

Lisette is a new programming language that brings Rust's safety and syntax to the Go ecosystem, eliminating nil-related errors and compiling directly into readable Go code.

Algebraic data types · Pattern matching · No nil ·

Hindley-Milner type system · Immutable by default

Interoperability with Go's ecosystem

import "go:fmt" import "go:io" import "go:os" fn load_config(path: string) -> Result<Cfg, error> { let file = os.Open(path)? defer file.Close() let data = io.ReadAll(file)? parse_yaml(data) } fn main() { match load_config("app.yaml") { Ok(config) => start(config), Err(e) => fmt.Println("error:", e), } }

Syntactically similar to Rust

enum Message { Ready, Write(string), Move { x: int, y: int }, } fn handle(msg: Message) -> string { match msg { Message.Ready => "ready", Message.Write(text) => f"wrote: {text}", Message.Move { x, y } => f"move to ({x}, {y})", } }

import "go:math" struct Point { x: float64, y: float64, } impl Point { fn distance(self, other: Point) -> float64 { let (dx, dy) = (self.x - other.x, self.y - other.y) math.Sqrt(dxdx + dydy) } }

fn describe(score: int) -> string { let grade = if score >= 90 { "A" } else if score >= 70 { "B" } else { "C" } let stars = { let count = score / 20 strings.Repeat("*", count) } f"{grade} {stars}" }

fn server_url() -> string { let scheme = os.LookupEnv("HTTPS") .filter(|s| s == "1") .map(|_| "https") .unwrap_or("http") let host = os.LookupEnv("HOST") .map(|s| strings.TrimSpace(s)) .filter(|s| s.length() > 0) .unwrap_or("localhost") let port = os.LookupEnv("PORT") .unwrap_or("8080") scheme + "://" + host + ":" + port }

interface Metric { fn label(self) -> string fn value(self) -> float64 } fn report(metrics: Slice<Metric>) { for m in metrics { fmt.Println(m.label(), m.value()) } } fn max<T: Metric>(metrics: Slice<T>) -> T { metrics.fold(metrics[0], |a, b| if a.value() > b.value() { a } else { b } ) }

type Headers = Map<string, string> fn handle_headers(h: Headers) -> Result<(), string> { if let Some(token) = h.get("Authorization") { let user = authenticate(token)? authorize(user)? } else { return Err("missing credentials") } let Some(id) = h.get("X-Request-ID") else { return Err("missing request ID") } process(id) }

Go runtime issues, caught at compile time

🔴 match is not exhaustive ╭─[example.lis:4:3] 2 │ enum Severity { Low, High, Critical } 3 │ fn should_alert(s: Severity) -> bool { 4 │ match s { · ───┬─── · ╰── not all patterns covered 5 │ Severity.Low => false, 6 │ Severity.High => true, 7 │ } ╰──── help: Handle the missing case Severity.Critical, e.g. Severity.Critical => { ... }

🔴 nil is not supported ╭─[users.lis:3:12] 1 │ fn find(name: string) -> Option<User> { 2 │ if name.is_empty() { 3 │ return nil · ─┬─ · ╰── does not exist 4 │ } 5 │ db.lookup(name) 6 │ } ╰──── help: Absence is encoded with Option<T> in Lisette. Use None to represent absent values

🟡 Result is silently discarded ╭─[files.lis:7:3] 5 │ fn cleanup() -> Result<(), error> { 6 │ os.RemoveAll("cache_dir")? 7 │ os.Remove("temp.txt") · ──────────┬────────── · ╰── failure will go unnoticed 8 │ } ╰──── help: Handle this Result with ? or match, or explicitly discard it with let _ = ...

🟡 Private type Config in public API ╭─[config.lis:6:24] 5 │ struct Config { host: string, port: int } 6 │ pub fn new_config() -> Config { · ───┬── · ╰── private 7 │ Config { host: "localhost", port: 8080 } ╰──── help: Config is private but exposed by new_config, which is public. Add pub to the private type or remove it from the public API

🔴 Immutable argument passed to mut parameter ╭─[sort.lis:5:13] 4 │ let nums = [3, 1, 2] 5 │ sort.Ints(nums) · ──┬─ · ╰── expected mutable, found immutable 6 │ } ╰──── help: Bindings in Lisette are immutable by default. Use let mut nums = ... to allow mutation

🔴 Struct Server is missing fields ╭─[server.lis:10:11] 9 │ fn start(mux: http.Handler) { 10 │ let s = Server { handler: mux } · ───┬── · ╰── missing fields: db, logger 11 │ http.ListenAndServe(":8080", s.handler) 12 │ } ╰──── help: Initialize all fields in this struct literal

Designed for interoperability with Go

import "go:strings" fn slugify(input: string) -> string { input |> strings.TrimSpace |> strings.ToLower |> strings.ReplaceAll(" ", "-") } slugify(" Hello World ") // => "hello-world"

fn load_config() -> Config { let result = try { let data = os.ReadFile("app.toml")? parse_toml(data)? } match result { Ok(config) => config, Err(_) => Config.default(), } }

fn fetch_primary() -> string { ... } fn fetch_replica() -> string { ... } let ch1 = Channel.new<string>() let ch2 = Channel.new<string>() task { ch1.send(fetch_primary()) } // goroutine task { ch2.send(fetch_replica()) } // goroutine let quickest = select { match ch1.receive() { Some(v) => v, None => "closed", }, match ch2.receive() { Some(v) => v, None => "closed", }, }

#[json(camel_case)] struct UserProfile { user_name: string, // => json:"userName" #[json("userID")] account_id: int, // => json:"userID" #[json(omitempty)] bio: Option<string>, // => json:"bio,omitempty" #[json(string)] score: int64, // => json:"score,string" #[tag("validate", "required")] email: string, // => validate:"required" #[json(skip)] internal_id: int, // => json:"-" }

fn safe_divide(a: int, b: int) -> Result<int, string> { let result = recover { a / b } // => Result<int, PanicValue> result.map_err(|pv| pv.message()) } match safe_divide(10, 0) { Ok(v) => fmt.Println(v), Err(e) => fmt.Println(e), }

fn run(query: string) -> Result<(), error> { let db = connect()? defer db.Close() let tx = db.Begin()? defer tx.Rollback() tx.Exec(query)? tx.Commit() }

Compiles to understandable Go

fn classify(opt: Option<int>) -> string { match opt { Some(x) if x > 0 => "positive", Some(x) if x < 0 => "negative", Some(_) => "zero", None => "none", } }

func classify(opt lisette.Option[int]) string { if opt.Tag == lisette.OptionSome { x := opt.SomeVal if x > 0 { return "positive" } if x < 0 { return "negative" } return "zero" } return "none" }

fn combine() -> Result<int, string> { let x = first()? let y = second()? Ok(x + y) }

func combine() lisette.Result[int, string] { check_1 := first() if check_1.Tag != lisette.ResultOk { return lisette.MakeResultErrint, string } x := check_1.OkVal check_2 := second() if check_2.Tag != lisette.ResultOk { return lisette.MakeResultErrint, string } y := check_2.OkVal return lisette.MakeResultOk[int, string](x + y) }

© 2026 Now Let Us. All rights reserved.

Source: Hacker News

Advertisement
Ad slot ready: 5887729102

More in this category

NOW LET US Related – Leaving Mozilla

dev-tools

Leaving Mozilla

A poignant and candid reflection from a 15-year Mozilla veteran upon their departure. The author highlights the leadership's missteps in trying to emulate tech giants and urges Mozilla to return to its core values: community and uniqueness.

NOW LET US Related – Shepherd's Dog: A Game by the Most Dangerous AI Model

dev-tools

Shepherd's Dog: A Game by the Most Dangerous AI Model

A developer tested Anthropic's latest, supposedly 'too dangerous' AI model by asking it to build a long-held game idea in a single shot. The model succeeded, generating a complete 2,319-line game after a 45-minute reasoning session.

NOW LET US Related – Open source AI must win

dev-tools

Open source AI must win

If artificial intelligence becomes a utility rented only from a few closed institutions, humanity loses its operational freedom. Open-source AI is a vital infrastructure for the future of our digital society.

NOW LET US Related – Statement on US government directive to suspend access to Fable 5 and Mythos 5

dev-tools

Statement on US government directive to suspend access to Fable 5 and Mythos 5

The US government has issued an export control directive forcing Anthropic to suspend all access to its Fable 5 and Mythos 5 models due to national security concerns, a move the AI safety startup strongly disputes.

NOW LET US Related – Electric motors with no rare earths

dev-tools

Electric motors with no rare earths

Renault Group is pioneering the development of electrically excited synchronous motors (EESM) that eliminate the need for rare earth magnets, reducing dependency on global monopolies while driving efficiency and sustainability.

NOW LET US Related – Swift at Apple: Migrating the TrueType hinting interpreter

dev-tools

Swift at Apple: Migrating the TrueType hinting interpreter

Apple has rewritten its TrueType hinting interpreter from C to memory-safe Swift for its Fall 2025 OS releases, improving security and boosting performance by an average of 13%.

EXPLORE TOPICS

Discover All Categories

Deep dive into the specific technology sectors that matter most to you.