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

推荐订阅源

V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
博客园 - 【当耐特】
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
Check Point Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
美团技术团队
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
IT之家
IT之家
T
Tailwind CSS Blog
月光博客
月光博客
Vercel News
Vercel News
V
V2EX
Engineering at Meta
Engineering at Meta
B
Blog
Stack Overflow Blog
Stack Overflow Blog
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
腾讯CDC
I
InfoQ

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.