5 ms·
RSC for Lisp Developers
- deleted 1y ago[deleted]
- fn-mote 1y agoThis post is almost vacuous. It explains quoting and then goes on to say: > I don’t understand LISP well enough to understand [...] Readers would be better off spending their time on a post with content. For example, Racket has a webserver that uses continuations. Whether or not that's something you are interested in, at least it has intellectual content. https://docs.racket-lang.org/continue/index.html https://docs.racket-lang.org/continue/index.html
- danabramov 1y agoWould you say I mischaracterise LISP, or the analogy between quoting and sending modules doesn’t apply? As I say in the article, I’m not familiar enough with LISP to understand how Electric works, but I’m a bit confused why you say there’s no content. I'm making a connection between the paradigms; if you find it vacuous, I think it would help to focus the criticism on the connection itself (why doesn't it hold?) rather than on me admitting the gaps in my knowledge. I appreciate the link you’ve shared about Racket. From what I see, their continuations seem server-only, i.e. there’s no way to express client-side code in Racket (beyond HTML). What I’m interested is a more mixed approach where LISP orchestrates both server and client code, which would be a closer analogy to RSC.
- judofyr 1y agoFrom the article: > It marks a piece of code to be treated as data (to be sent to the client). > 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. Eventually this code will make it to the client (as a <script>) and be evaluated there. The point of quoting in Lisp is that you get the code actually as data: You can introspect it ("how many string literals are there in here"), rewrite it ("unroll every loop once"), serialize it, store it in a database. And more importantly: The code is structured in the same way as any data in a regular program (lists). It's not hard for the developer to do any of these things. If I get back '/js/chunk123.js#onClick' I simply have a reference, which I can use to invoke it remotely. The code appears to still be sent as bundled JavaScript, evaluated as usual, and then linked together with the reference. There's a small connection to code-as-data in the sense that you need to be able serialize code in order to share it between a server/client, but other than that I don't really see much of a connection.
- danabramov 1y agoSure, and the article does acknowledge that directly: >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. To me, the connection is that I'm able to treat a reference to serialized code as a first-class primitive that can be passed around the server code (and composed via component tag composition), but indeed it's not full-on metaprogramming.
- kaoD 1y agoAs someone that knows both Lisp and RSC, I don't think this is a great analogy since it misses nuances and intention in both sides of the equation. The crux of Lisp's code-is-data-is-code is that you can manipulate S-expressions since they're a very simple data structure (think metaprogramming). I know you touched upon this in the article but acknowledging it doesn't make it less central to the issue. I don't see the parallels except a very superficial similarity due to code being "serialized" (for lack of a better term, since that's not even what Lisp does) but that's just (1) a technical detail that glosses over the actual intention/capabilities and (2) not even true if we go down to the technicals. But that might just be my personal priors, so take it with a grain of salt.
- danabramov 1y agoTo me, the common thing is having a first-class way to deal with something that's poised to execute later. RSC's way to do it is opaque, whereas quoting isn't opaque. In that sense, quoting is more powerful — which is why it can express both RSC and more mixed paradigms like Electric. But I think it's a meaningful connection because it's both about intent and capabilities. There aren't a lot of programming paradigms that enable cross-runtime composition and orchestration.
- nothrabannosir 1y agoI thought this would be about the equivalent to LiveView in Lisp. An example from Common Lisp with actual meat: https://40ants.com/reblocks/quickstart/ https://40ants.com/reblocks/quickstart/
- danabramov 1y agoThanks for sharing! This is indeed close in some ways — make-js-action roughly corresponds to "use server" in RSC (https://overreacted.io/what-does-use-client-do/#use-server https://overreacted.io/what-does-use-client-do/#use-server). However, I don't think this actually allows writing client-side logic in LISP too (beyond HTML that submits forms)? The point of RSC is to have the programming model actually span both sides. That's why I brought up Electric in the end, which does do that.
- worthless-trash 1y agoStill dont know what RSC is from this page. As a lisp developer and not a javascript developer, I don't understand how onclick ends up with '/js/chunk123.js#onClick' Maybe this is more meaningful for javascript developers. It makes little sense to me.
- jjraden 1y agoI'm guessing they mean React Server Components, but yeah, it annoyed me too that not only do they not define the acronym, but it appears only once on the page -- the title -- so that it's harder to infer it from context.
- danabramov 1y agoGreat callout, thanks! Edited. I meant the article more as "if you're already curious about the RSC model and have some LISP background" rather than an introduction to what RSC is, but hopefully spelling it out at least helps with that context.
- danabramov 1y agoWhen a compiler sees an import to a module with “use client”, it substitutes it with this reference. So the server code only sees the reference. Whereas the compiler also takes this as an instruction to bundle the code from that entry point. (Which ensures this reference actually corresponds to a file that will exist.) Does this make sense? Like I said, I might be stretching the analogy, but it’s a bit like quoting except at the module system level (and in practice mostly happening at the build time). I've edited the post to clarify this a bit.
- worthless-trash 1y agoThanks, that makes more sense.
- owebmaster 1y agoThere is a weird push/rebranding of React to actually run in the server, like Ruby on Rails or Django. > It makes little sense to me. You are not alone and I've been coding JS for the past 20 years. Well, it makes little technical sense to me but it is not difficult to find where it might makes more sense.
- sktrdie 1y agoWill this whole idea of writing more server-side logic pay off? I'm not sure. It felt like we were moving towards dumb backends that sync automatically towards frontends that would contain most logic. Things like https://localfirstweb.dev/ https://localfirstweb.dev/ or https://electric-sql.com/ https://electric-sql.com/ felt like the future Writing more server code (as quoting/react-server-components are suggesting) will increase the surface area where errors can occur. Limiting that to either just the server/client feels like a much saner approach
- danabramov 1y agoThat's a good question! I'll maybe post some time about that. I don't think sync engines are "the future" although they have their uses. But if you care about large-scale aggregation, private data with sophisticated permission models, aggregation across private data, feeds, and such, server/client is a much more powerful model. For example, I don't think you can implement something like Twitter in a pure peer-to-peer fashion without compromising on functionality a lot.
- qudat 1y ago> I don't think sync engines are "the future" although they have their uses I think the same argument applies to RSC. For many use cases, it doesn't make sense. Many organizations and projects do not need SEO or server code specifically for their FE. If the organization has committed to an API service in order to support a range of clients then RSC/react server framework is "pure overhead." As someone who has been building with React for a decade, RSC was the moment where I felt the complexity vastly outweighed the benefit. I'm in a position where I can argue that SPAs are dramatically simpler to implement compared to RSC/nextjs, which I think would be surprising to outsiders who bemoan SPAs as complex. I find the "preload then rehydrate" data synchronization model simpler to understand and can turn even the slowest APIs into an app that feels instant: https://starfx.bower.sh/learn#data-strategy-preload-then-refresh https://starfx.bower.sh/learn#data-strategy-preload-then-ref...
- danabramov 1y ago
- deleted 1y ago[deleted]
- diggan 1y ago> I’ll try to learn LISP too, someday. It's funny, as I could probably credit Dan with the reason I mostly spend time with Clojure and ClojureScript today. I think ClojureScript/Reagent/Om was mentioned really quickly when he did the "Hot Reloading / Time Traveling" talk back in 2014 sometime, which eventually led me to find Clojure which basically was made for making those things easy for the entire stack, not just frontend. So thanks Dan for leading me to greener pastures, but a shame you still haven't taken the time to look into any lisp! Reagent+ClojureScript should be (relatively) familiar to you, as long as you get over the parenthesis-avoidance stage most of us go through :)
- danabramov 1y agoHaha, thanks! Yeah maybe now I'm on a sabbatical, I can actually play with a few things. I've also seen https://romanliutikov.com/blog/towards-react-server-components-in-clojure-part-1 https://romanliutikov.com/blog/towards-react-server-componen... recently so kind of curious how that progresses.
- codr7 1y agoClojure is far from the whole truth when it comes to Lisp though. Common Lisp doesn't have as many opinions about your code, includes several nice features that Clojure skipped, and isn't chained to the JVM.
- diggan 1y ago> Clojure is far from the whole truth when it comes to Lisp though. That's true for sure, and I'm sorry if my comment gave that impression, I'm not trying to say that Clojure is the only lisp, or even the best lisp! Just the one that fit me and my problems the best. > and isn't chained to the JVM. Neither is Clojure (the language), as it's available with JavaScript as a host (ClojureScript), LLVM (Jank) or even the Erlang VM (Clojerl). I'm sure there are more out there too, but the Clojure-JVM runtime isn't the only one available. With that said, lots of people say Common Lisp is another good lisp, and been deployed in production for many decades, so I'm sure it's another great choice if anyone wanna get deeper into lisps. I personally haven't taken the time (yet!) to get to know it on any deeper level, so would be weird to recommend it before another lisp I know much better.
- Philpax 1y agoThat's four posts about RSC in about as many days. Dan, please, you've got to pace yourself :sweat_smile:
- danabramov 1y agoI kind of alternate between not being able to write and writing too fast so I try to catch the wave when it happens.
- randomuxx 1y agoMaybe I'm slow, but after countless posts about RSC, I still don't get the appeal. Is it really worth the headache and extra complexity? Caveat: I've used Vue more than any other FE library/framework, but for the last 3 years I worked exclusively with React (via Next—app router). The company I worked (I left in Jan) for jumped on this RSC train as soon as it was released and boy,oh boy was it a mess! We ofteb got direct support from Vercel when our shit will break or not work as expected... To say the app was slow and behaved unexpected would be an understatement. Eventually, they had to rewrite everything back as a SPA.
- danabramov 1y agoI think RSC itself is pretty solid by this point but frameworks around it (primarily Next.js) are still somewhat rough (and were much rougher during the initial App Router release). Hard to say more without knowing what kind of issues you were hitting. I'm posting because I find the technology interesting. I don't have a goal of convincing you to use or adopt it. I sometimes write about specific aspects that I find appealing but YMMV.
- randomuxx 1y agoFair Dan, and I appreciate your response. I also hope you understand I wrote this based on my experience with it. ♥
- danabramov 1y agoSure! Do you recall what kind of issues or bugs you were hitting?
- kaoD 1y agoMaybe it's where I'm imagining we're headed (and not where we're actually headed) but I think it will bring us into the sweet spot that I want/need: good old PHP-like server-rendered sites (or even static pages) with custom interactive components (think e.g. forms with client-side validation) without the mess that mixing PHP+jQuery used to be. Server rendering is enough for the 80% use case. Browsers are optimized for it. Sprinkle interactivity without the impedance mismatch of jQuery and you're in heaven. No more overengineered state syncing between client and server. Just. Fetch. HTML. Currently frameworks are trying to shoehorn it into the 2018 React mindset but that's not what I think is needed for them to succeed.
- flufluflufluffy 1y agoIt’s less “RSC for Lisp Developers” and more “‘use client’ for people who know what strings are” xD
- danabramov 1y agoMaybe somewhere in the middle? :) "use client" is more first-class than wrapping code in a string because it gives you an opaque reference to the module and its dependencies in a way that gets seamlessly unwrapped on the other machine. It doesn't really feel like dealing with strings because it's integrated with the module system. But yes, it's opaque unless quoting.
- revskill 1y agoMaybe, if you dropped React from RSC, you got only Server component, it means something more generical for you. Now is it just html ? Yup, Html returning from server is a server component, executed by browser with DOM API (for script tag). So if you understand Html and JS, you should understand RSC right ? THe point here is, your html doesn't get rendered on server, your <script> tag doesn't get executed on server. The server returns a program (code is data) to browser to render the document and execute script. The real trick, is the server understands the html syntax (using string literal), so you got the illusion of isomorphism between 2 computers. The server acts as "program generator", the client acts as "program executor". Ok, it's just one piece of the whole. The hard trick, is how to keep state preserved between re-rendering.
- Zak 1y agoI wonder what things would look like today if Netscape had stuck with its first idea of embedding Scheme instead of creating Javascript.
- mighmi 1y agoPerhaps paradise. The browser as a lisp machine, ah... Dreams. The spritely team is making strides to using Guile in WASM, but it's nothing like s expr instead of JSON etc. could have been. https://files.spritely.institute/docs/guile-hoot/0.1.0/Introduction.html https://files.spritely.institute/docs/guile-hoot/0.1.0/Intro...
- kazinator 1y agoThere would still be alternative languages in the browser ecosystem. Just they wouldn't have transpile to an idiotic target.
- potholereseller 1y agoIt would probably depend on the Scheme/Lisp implementation and how it was secured. If it used a Scheme implementation like in Halo:CE, then people would have justifiably hated it. If it used something more like MIT-Scheme, people might've been okay with it. But I suspect it would get the same hate that JS gets, since there is a lot of low-quality JS code floating around -- even though JS itself isn't remotely that bad -- and you would instead have a lot of low-quality Scheme code floating around. Damned if you do, damned if you don't. FWIW, it is feasible to put Scheme/Lisp in a browser today, and it might even be fun. Take a browser that lacks JS (e.g. Dillo, w3m); figure out how to add Firefox's or Chromium's approach to isolating each Javascript instance; and embed a Scheme or Common Lisp implementation (e.g. Chez Scheme [1] or ECL [2]). You will need to decide what Scheme/Lisp functions/macros to include/exclude. It may seem obvious to exclude file operations, but they did that with JS and now we have IndexedDB; a restricted, virtual file system might be fun to play with. Multithreading might seem like a great thing to include, until you start trying to implement secure multithreading. I would start with whatever cl-isolated [3] allows and expand/contract from there. And before anyone asks, "would this actually be worth implementing in 2025?", the answer is decidely "yes". You could build powerful desktop applications without the full weight of Electron. You could develop local-network webapps for you and/or your company. But I think it would be a bad idea to deploy this on the open internet without first spending a lot of time securing the browser overall. Another option is resurrecting Closure [4], which is written entirely in Common Lisp. In that, you could go on a wild tangent and support multiple scripting languages (e.g. Common Lisp via cl-isolated, cl-forth [5], cl-javascript [6], cl-python [7], scheme88 [8], and even Coalton [9]). [1] <https://old.reddit.com/r/scheme/comments/a3oogf/questions_on_embedding_chez_scheme_into_a_c_app/ https://old.reddit.com/r/scheme/comments/a3oogf/questions_on...> [2] With ECL, you could use cl-isolated in addition to OS-level containerization, to achieve more defense-in-depth. Or maybe port cl-isolated to Chez Scheme. [3] <https://github.com/kanru/cl-isolated/ https://github.com/kanru/cl-isolated/> [4] <http://closure.common-lisp.dev http://closure.common-lisp.dev> [5] <https://github.com/gmpalter/cl-forth https://github.com/gmpalter/cl-forth> [6] <https://marijnhaverbeke.nl/cl-javascript/ https://marijnhaverbeke.nl/cl-javascript/> [7] <https://clpython.common-lisp.dev/ https://clpython.common-lisp.dev/> [8] <http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/scheme/impl/scheme88/ http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/s...> [9] <https://github.com/coalton-lang/coalton https://github.com/coalton-lang/coalton>
- deleted 1y ago[deleted]