惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
雷峰网
雷峰网
The Cloudflare Blog
WordPress大学
WordPress大学
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
IT之家
IT之家
V
V2EX
博客园 - 司徒正美
小众软件
小众软件
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Hugging Face - Blog
Hugging Face - Blog
T
Tailwind CSS Blog
Last Week in AI
Last Week in AI
Jina AI
Jina AI
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿

overreacted — A blog by Dan Abramov

How I Vibed a Proof of Conway’s Conjecture — overreacted There Are No Instances in atproto — overreacted Algebraic Effects for the Rest of Us — overreacted A Social Filesystem — overreacted Introducing RSC Explorer — overreacted Hire Me in Japan — overreacted How to Fix Any Bug — overreacted Where It's at:// — overreacted Open Social — overreacted A Lean Syntax Primer — overreacted Beyond Booleans — overreacted The Math Is Haunted — overreacted Suppressions of Suppressions — overreacted I'm Doing a Little Consulting — overreacted How Imports Work in RSC — overreacted Progressive JSON — overreacted Why Does RSC Integrate with a Bundler? — overreacted One Roundtrip Per Navigation — overreacted Static as a Server — overreacted RSC for Astro Developers — overreacted Functional HTML — overreacted What Does "use client" Do? — overreacted Impossible Components — overreacted JSX Over The Wire — overreacted React for Two Computers — overreacted The Two Reacts — overreacted A Chain Reaction — overreacted npm audit: Broken by Design — overreacted Before You memo() — overreacted The WET Codebase — overreacted
RSC for LISP Developers — overreacted
2025-06-01 · via overreacted — A blog by Dan Abramov

One of the big ideas of LISP is that code is data, and data is code. I mean, that’s kind of generally true, but in LISP it’s both culturally and syntactically emphasized. For example, let’s take this piece of code in LISP:

(+ 2 2)

This gives us 4.

But let’s put a quote before it:

'(+ 2 2)

Suddenly, the result is… (+ 2 2).

Uh, what do I do with that? Well, that’s a piece of LISP code. “Quoting” a piece of LISP code means “don’t actually evaluate it, just give me the code itself”.

Of course, I could evaluate it later:

(eval '(+ 2 2))

This gives me 4 again.

That’s what I mean by “code is data” being very much in the LISP culture. The language has a first-class primitive for “don’t execute this part”. That’s quoting.

Now consider web apps.

A web server is a program whose job is to generate another program. A server generates the client program (written in HTML and JavaScript) and serves it to the client computer. Generating and sending code sounds an awful lot like quoting.

In JavaScript, we don’t have quoting. I can’t put a ' before a function and say “now I want to treat this as data rather than code”. Well, I could wrap it into a string literal, but there would be no syntax highlighting and it would kind of lose too much syntatic power. You really don’t want to be coding inside string literals.

We can’t “quote” individual code blocks in JavaScript without losing many benefits of the language. However, what if we could “quote”… an entire module?

React Server Components (RSC) is a client-server programming paradigm that uses a similar idea to refer to client code from the server code. The 'use client' directive lets you import code designed for the client—but without running it:

'use client'
 
export function onClick() {
  alert('Hi.');
}

Like quoting, it marks a piece of code to be treated as data. Unlike quoting in LISP, the result you get back is opaque—you can’t transform or introspect that code.

This means that whoever imports onClick from the backend code won’t get an actual onClick function—instead, they’ll get '/js/chunk123.js#onClick' or something like that identifying how to load this module. It gives you code-as-data. Unlike with LISP quoting, this is implemented at the compile time using a bundler.

Eventually this code will make it to the client (as a <script>) and be evaluated there. Then, the onClick function will actually exist (and maybe even be called).

What this gives us is an ability to write a program that composes behaviors that execute at different stages (on the server and the client) in a very modular way. See here for example. The parts outside the “quote” deal with server-only resources, while the parts inside the “quote” are stateful and exist on the client—but they are composed. The server stuff can wrap the client stuff, the client stuff can wrap the server stuff, as long as you’re doing all composition from the server. And what doing composition on the server enables is a guarantee that all the server stuff runs within a single request/response roundtrip. It’s also progressively streamed.

That’s kind of it, really. Of course, this is a lot less powerful than quoting because the evaluation strategies are being prescribed by React, and there’s no kind of metaprogramming like transforming the code itself. So maybe it’s still a stretch.

I know LISP has a rich tradition of solutions that compose code across multiple environments, with some newer approaches like Electric picking up steam. I don’t understand LISP well enough to dig deep into them but I would love to see more explanations targeted at JavaScript developers, both about prior art and new ideas.

Thank you!

I’ll try to learn LISP too, someday.