Scoopfeeds — Intelligent news, curated.
computer-science

Rust but Lisp

Hacker News · May 9, 2026, 9:46 PM

Key takeaways

  • A transparent s-expression frontend that compiles directly to Rust — no runtime, no GC, just (s-expr → .rs → binary).
  • "Distance: {}" (. p1 distance (& p2)))) Everything Rust has — ownership, borrowing, lifetimes, generics, traits, pattern matching — expressed as s-expressions.
  • git clone https://github.com/ThatXliner/rlisp.git cd rlisp cargo install --path .

Rust semantics with LISP syntax. A transparent s-expression frontend that compiles directly to Rust — no runtime, no GC, just (s-expr → .rs → binary).

(struct Point (x f64) (y f64)) (impl Point (fn distance ((&self) (other &Point)) f64 (let dx (- (. self x) (. other x))) (let dy (- (. self y) (. other y))) ((. dx powf 2.0) + (. dy powf 2.0)) sqrt)) (fn main () () (let p1 (new Point (x 0.0) (y 0.0))) (let p2 (new Point (x 3.0) (y 4.0))) (println! "Distance: {}" (. p1 distance (& p2)))) Everything Rust has — ownership, borrowing, lifetimes, generics, traits, pattern matching — expressed as s-expressions. No semantic gap. rustc does type checking, borrow checking, and optimization. rlisp just handles the syntax.

git clone https://github.com/ThatXliner/rlisp.git cd rlisp cargo install --path . Usage rlisp compile file.lisp # transpile to file.rs rlisp build file.lisp # transpile and compile with rustc rlisp run file.lisp # transpile, compile, and run Syntax map LISP Rust (fn add ((x i32) (y i32)) i32 (+ x y)) fn add(x: i32, y: i32) -> i32 { (x + y) } (let x i32 42) let x: i32 = 42; (struct Point (x f64) (y f64)) struct Point { x: f64, y: f64 } (enum Option (T) (Some T) None) enum Option<T> { Some(T), None } (match val ((Some x) (handle x)) (None ())) match val { Some(x) => { handle(x) }, None => { } } (if (> x 0) (println! "yes") (println! "no")) if (x > 0) { println!("yes") } else { println!("no") } (impl Point (fn new (...) ...)) impl Point { fn new(...) ... } (trait Display (fn fmt (...) Result)) trait Display { fn fmt(...) -> Result; } (new Point (x 1.0) (y 2.0)) Point { x: 1.0, y: 2.0 } (. obj field) obj.field (. obj method arg) obj.method(arg) ([] arr 0) arr[0] (foo! args) foo!(args) (println! "{}" x) println!("{}", x) (loop (println! "tick")) loop { println!("tick") } (while (> x 0) (-= x 1)) while x > 0 { x -= 1 } (for x in 0..10 (println! "{}" x)) for x in 0..10 { println!("{}", x) } (lambda (x y) (+ x y)) |x, y| { x + y } (pub fn foo () i32 42) pub fn foo() -> i32 { 42 } (pub (crate) mod m (fn f () () ())) pub(crate) mod m { fn f() {} } (use std::collections::HashMap) use std::collections::HashMap; (const MAX usize 1024) const MAX: usize = 1024; (rust "let x: i32 = 42; x") let x: i32 = 42; x Binary operators (+, -, *, /, ==, !=, <, >, &&, etc.) emit infix: (+ a b) → (a + b).

Article preview — originally published by Hacker News. Full story at the source.
Read full story on Hacker News → More top stories
Aggregated and edited by the Scoop newsroom. We surface news from Hacker News alongside other reporting so you can compare coverage in one place. Editorial policy · Corrections · About Scoop