Coding

Rust but Lisp

A new Rust library, "rust-but-lisp," injects a Lisp-like macro system into the statically typed language, blurring the lines between compile-time and runtime evaluation. By leveraging Rust's procedural macros, the library enables developers to write code that can be evaluated and transformed at compile-time, effectively merging the benefits of static typing with the flexibility of dynamic evaluation. This fusion of paradigms could redefine the way developers approach code generation and metaprogramming.

A new command-line tool called rlisp lets you write Rust programs using Lisp-style s-expressions. It is a transparent frontend: you write .lisp files, and rlisp transpiles them to .rs files, which are then compiled by rustc. There is no runtime, no garbage collector, and no semantic gap — the generated Rust code uses ownership, borrowing, lifetimes, generics, traits, and pattern matching exactly as you would write them by hand.

What it does

rlisp maps Lisp syntax directly to Rust constructs. For example:

  • (fn add ((x i32) (y i32)) i32 (+ x y)) becomes fn add(x: i32, y: i32) -> i32 { (x + y) }
  • (struct Point (x f64) (y f64)) becomes struct Point { x: f64, y: f64 }
  • (let x i32 42) becomes let x: i32 = 42;
  • (if (> x 0) (println! "yes") (println! "no")) becomes if (x > 0) { println!("yes") } else { println!("no") }

Binary operators like +, -, *, /, ==, !=, <, > are emitted infix: (+ a b)(a + b).

The tool supports all major Rust features: closures (typed and untyped, move closures), modules with visibility (pub, pub(crate), pub(super)), use imports with renaming, match expressions, loop/while/for loops (including destructuring in for), and inline raw Rust via (rust "...") for anything the s-expression syntax does not express natively.

Macros without proc_macro

A key feature is the macro system. rlisp macros are compile-time s-expression transformers — no proc_macro crate, no token streaming, no syn/quote. A macro is simply a function from s-expressions to s-expressions. It uses three special forms:

  • (quasiquote template) — quote a template but allow unquotes inside
  • (unquote name) — insert the value of name into the template
  • (unquote-splicing name) — splice a list into the surrounding form

Example: a when macro:

(defmacro when (condition &rest body)
  (quasiquote (if (unquote condition)
                  (do (unquote-splicing body)))))

(when (> x 10) (print "big") (print "huge")) expands to (if (> x 10) (do (print "big") (print "huge"))), which compiles to if x > 10 { print("big"); print("huge") }.

How to install and use

git clone https://github.com/ThatXliner/rlisp.git
cd rlisp
cargo install --path .

Three commands:

  • 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

Tradeoffs

rlisp is a syntax layer only. It does not change Rust's semantics, type system, or borrow checker. The generated .rs file is what rustc sees, so all Rust rules apply. The main tradeoff is readability for teams unfamiliar with s-expressions. The author describes the project as "mostly for fun — an exploration of what Rust looks like when you strip away the syntax and keep the semantics." Practical benefits include trivial macros (no proc_macro ceremony) and structural editing (slurp, barf, transpose, wrap — every operation is balanced by construction).

When to use it

This is not a production tool for most teams. It is useful for:

  • Experimenting with Lisp-style metaprogramming in a Rust context
  • Teaching or demonstrating Rust semantics without syntax distractions
  • Projects where macro simplicity outweighs the s-expression learning curve
  • Anyone who wants to write Rust with parentheses

Bottom line

rlisp is a well-executed syntax experiment that compiles Lisp to Rust with zero runtime overhead. The macro system is genuinely simpler than Rust's proc_macro. If you are comfortable with s-expressions and want to explore what Rust looks like in that form, it is worth a look. For most Rust work, the standard syntax remains the practical choice.

Similar Articles

More articles like this

Coding 1 min

Visual Studio Code 1.120

Visual Studio Code’s 1.120 update slashes debugging friction with native Data Breakpoints, letting engineers pause execution when specific object properties change—not just memory addresses. The release also bakes in GitHub Copilot-powered inline code completions for Python, JavaScript, and TypeScript, cutting keystrokes by up to 40% in early benchmarks, while a revamped terminal shell integration finally bridges the gap between local and remote workflows.

Coding 1 min

"Dirty Frag" (CVE-2026-43284): The Second Linux Root Exploit in Eight Days

A devastating Linux root exploit, dubbed "Dirty Frag," has emerged, capitalizing on a previously unknown vulnerability in the Linux kernel's networking stack, specifically in the handling of IPv6 fragmentation (CVE-2026-43284). This marks the second high-severity Linux exploit in just eight days, underscoring the growing urgency for kernel patching and vulnerability mitigation in the face of escalating cyber threats. The exploit's ease of exploitation and widespread kernel adoption amplify its potential impact.

Coding 1 min

Bun ported to Rust in 6 days

A 6-day code sprint has successfully ported Bun, a high-performance JavaScript runtime, to Rust, a systems programming language, marking a significant milestone in the pursuit of native, zero-CPU-overhead execution for web applications. This achievement leverages Rust's ownership model and borrow checker to eliminate runtime errors and memory safety issues. The port's rapid completion underscores the growing appeal of Rust as a platform for building high-performance, secure, and efficient web infrastructure.

Coding 1 min

GrapheneOS fixes Android VPN leak Google refused to patch

Android's VPN security gap, long dismissed by Google, has been plugged by GrapheneOS, a custom Android variant, through a patch that exploits a workaround for a kernel vulnerability, effectively bypassing the company's refusal to address the issue. The fix leverages a Linux kernel module to intercept and encrypt VPN traffic, circumventing a known flaw in Android's VPN implementation. This patch underscores the limitations of Google's control over Android's security.

Coding 1 min

Show HN: Mochi.js: bun-native high-fidelity browser automation library

A Bun-native browser automation library, Mochi.js, bypasses anti-bot defenses by eschewing superficial client-side probes in favor of raw Chrome DevTools Protocol (CDP) parity with stock Chromium, outperforming forked browsers by avoiding detectable artifacts. Built on a WAF-aware probe manifest, it targets the actual heuristics used by CAPTCHAs and web application firewalls, enabling high-fidelity automation without the need for deception. The framework’s JS-layer approach redefines browser automation by prioritizing consistency over cosmetic mimicry.

Coding 1 min

Bun's experimental Rust rewrite hits 99.8% test compatibility on Linux x64 glibc

Rust's growing adoption gets a significant boost as Bun, a high-performance JavaScript runtime, achieves near-flawless test compatibility on Linux x64 glibc with its experimental Rust rewrite, boasting an impressive 99.8% test pass rate. This milestone marks a crucial step towards mainstream adoption of Rust in the Linux ecosystem. The achievement underscores the potential for Rust to become a go-to language for building high-performance, secure applications.