A Personal Software Runtime inspired by Emacs, Plan 9, Erlang, Hypermedia, and Unix
88 points by mysticmode
88 points by mysticmode
Hi! Author here. Pleasantly surprised to see vrs in my rss feed.
This was a project started at the Recurse Center during my time there. Still early days for a hobby project… but I’m excited it caught your eye!
You should record a 5 min video showing your setup! It’s magical and helped me get why you’d want this, not just how it’s built.
Hey Chris! :wave:
(for context - he’s seen me used this system live on my machine!)
Yes - I’m hoping to write about this… sometime in the near future!
Could you say a bit more about hypermedia? The thing that fascinates me most about Emacs is not that it’s an image-based LISP machine, but that it provides a uniform interface via literal hyper-text (linear text, not hierarchical dom, but with attributes), which to me seems the goldilocks point of user-interfaces — easier to manipulate directly and interactively than pure UNIX byte stream, but still allowing for composability, something that GUI apps are struggling with.
Emacs is my favorite plain-text computing environment for this very reason! Plan 9’s plumber and acme come to mind as well.
vrs’s current “hypermedia” approach is simple:
A close analogy may be Clojure’s EDN, in a world where EDN was used natively in browsers instead of HTML, and you owned a collection of apps as “mini-web browsers” to render the markup in a context-appropriate way.
Some (albeit very outdated) raw notes under “Lisp as Uniform Interface” here
One cool thing I’m able to do in the current implementation is run the same command bar code (and use its capabilities) in the terminal, in Emacs, and my GUI command bar.
This reminds me a bit of OpenDoc and BeOS translators. OpenDoc for compostable documents based on a common model, with pluggable specialised editors, and BeOS translators for providing reusable presentation components for various data formats. You’ve got some really good ingredients in this project!
How is it fundamentally different than an XML-based representation?
Like, I do get that lisps are more “elegant”, but for data-only use case I see no difference whatsoever.
Also: https://parentheticallyspeaking.org/articles/bicameral-not-homoiconic/
I don’t think there is a fundamental difference - in fact, it is an important point that sexprs can represent the exact same structure you’d have in XML-based representations!
The key is using the same exact concept for interface markup, data, and the code - and sharing the syntax, representation, and functions on that representation between them.
Lisps and XMLs can represent similar structures - but in my personal opinion I’d much prefer a programming language syntax like Lisp over XML.
I don’t feel that lisps are inherently elegant in all scenarios - but they make the right compromises in being a good enough thing for all things
there was an blog post relating XML to Lisp syntax I’m struggling to find…
Found it! https://web.archive.org/web/20250219043529/http://www.defmacro.org/ramblings/lisp.html
It looks very cool! Feels similar in some ways to Spritely Goblins which I’ve been using for a few years now, though with more of a built-in focus on scripting for calling external programs and without the capability security model.
Even though it’s not an exact fit in a couple ways, I’m wondering now if an OCapN implementation for vrs might be useful… maybe not, the message passing semantics seem a little bit different between the two. But maybe it could work!
I think this will definitely provide some inspiration for my side projects, though. :)
I’ve heard of Spritely and follow Guile, although I have not read / tried it myself… how do you like it?
I am hoping to add some sort of capability-based system in the future, but I don’t have it clear mental model quite yet. Definitely later in the roadmap :) I’ll make sure to checkout OCapN - thank you for the recommendation!
On Spritely: I love it. It’s definitely got a learning curve (especially if it’s your first time learning about object capabilities like it was for me), but learning it has changed the way I think about application programming in a lot of ways. I think for the better, though maybe it’s a curse since I’ll almost certainly never get to use this stuff at $dayjob. :)
On Guile I’m a bit more mixed; overall I like it as a Scheme, but its error messages can be a bit difficult to work with and starting new Guile projects involves dealing with Autotools which I’m not a fan of (though Guile Hall at least can take care of much of the initial setup). But I deal with all that because two of my favorite software projects (Spritely and Guix) use it, and that far outweighs any issues I have with Guile.
I am hoping to add some sort of capability-based system in the future, but I don’t have it clear mental model quite yet. Definitely later in the roadmap :)
Awesome! :D
I’ve been noodling on this a bit today and I feel like the parts of vrs that are perhaps the least capability-compatible as-is are the service discovery mechanism and the use of global PIDs for interprocess communication. The latter I think could be addressed by giving each process a c-list in the runtime (if I’m understanding the vrs architecture correctly). For processes spawned as procedures within another process of course you can rely on lexical scope; in the following example from your readme you’ve referenced parent_pid
in the body of the new process, which could work without changes if parent_pid
was a capability to the current process and the runtime put a reference to parent_pid
in the new process’s c-list.
# Message from child back to parent
(def parent_pid (self))
(spawn (lambda ()
(sleep 10)
(send parent_pid :hello_from_child)))
But for new services that don’t already have this context you need something to populate the new process’s c-list with some initial capabilities, leading back to the service discovery mechanism… which is a bit trickier.
I’ve been a fan of the service binding concept used by Cloudflare Workers, and I’ve started playing around with something similar in one of my (still very early PoC stage) Goblins projects. But this does require you to wire up which services should be able to talk to which others and their binding names, which admittedly does add some extra work for each new service. (And it probably implies that the runtime be responsible for spawning services with their bindings wired up, rather than the new services starting up on their own and registering themselves - otherwise, how do you know that the thing that just showed up is really the echo
service?)
Hopefully I’ve given you some things to think about and this wasn’t too much of an infodump 😅
Hopefully I’ve given you some things to think about and this wasn’t too much of an infodump 😅
This is fantastic, thank you for sharing! I’ll make sure get my hands on Spritely.
For locking down services, I’ve been thinking about applying code-signing and entitlements (for a service process to validate) - but I’m not quite sure how it’ll come together in a primarily “scripty” context of vrs / lyric. We’ll see!
Oh, right, a clarification/correction on one thing I mentioned, because I got myself a bit mixed up there. To do what I was describing re: the parent process passing a reference to the child process in a transparent way, you’d use the processes’ environments to control which processes have access to which references rather than a c-list.
Some more, ah, “light reading” on that: https://mumble.net/~jar/pubs/secureos/secureos.html
Do you have access to my brain? This is exactly what I want in a system, really impressive work. I look forward to poking at this.
I wanted to pull design features from systems I love (Emacs, etc) into one place! It has quirky inspirations - and picked up some of its own quirks along the way.
Happy to hear it resonates with you!
Ditto; this is the kind of system I’ve always wanted. I’ve been a heavy emacs user for decades, and can v readily envision how actors, state/objects, could make it so much better.
I’d like to see a Shen like system here; if/when I get to use this system, I’d like to port Shen.
I’m not familiar with Shen - what makes it special?
I love that so many of us are thinking about similar concepts! I’m putting yours on my reading list! I’ve always been more of a vim gal, but I always feel like I’m missing out on lisp editing tools in emacs so maybe I’ll have to give evil another try. Getting a good port of parinfer was huge. I very nearly made the switch to acme, but I missed my editing language too much.
tomo el agua is more of an art project than a serious erlang flavored lisp with plan9 characteristics. I want the virtual os to have an interesting shape that can leak into the game world once there’s enough of a graphics engine in there to run my stories.
I admit I don’t really understand this. What is it actually, for someone who is not really familiar with any of these? In other words: Explain it to me like you would to a 10 year old. :D
I don’t have the most insightful answer - but the simplest one is:
A programming language, runtime environment, uniform concepts, and a set of software tools, all inspired by quirky systems I love, that allows me to build my own personal software the way I want to!
This is kinda the end goal in mind with my project scheme-rs and the follow-up project GoukiLang (somewhat described here). It looks like Lyric solves a similar piece of the puzzle as scheme-rs!
I’m excited to take a look at these projects - thanks for sharing them!
My project is focused on very broad strokes across the stack today, to build an intuition of what I need from each component… but I’m looking forward to revisiting the language implementation soon. It’s quite poor / unsophisticated today (though good enough for E2E thinking).
When it’s time I’ll make sure to look at scheme-rs / Gouki!
Super cool project, must have taken a lot of work. Seeing the lisp/erlang mix reminded me of ABCL (https://dl.acm.org/doi/pdf/10.1145/28697.28722) where basically everything is async message passing, even object references to their super/meta class
What made you choose to write your own VM + lang over choosing something like BEAM + erlang/elixir?
I had a few reasons in mind:
I’m extremely interested in this. I’ve built many small experiments in a similar vein, and would love to put my energies behind a common initiative.
If you could share some screenshots /video that would really help me understand the tool in more concrete terms. I love the vision, I just want to get a better idea of what the implementation looks like :)
Thank you for sharing this.
Hey! This is an exciting note, but I’m not quite sure if I’m ready for contributors to the project. It’s intended to be a free-spirited, personal venture - and I plan to keep it that way for the time being until I get all the ideas I want to try out of my system.
That being said - I don’t mind forks! I’d be curious to see how others push the ideas they are inspired by.
The counter service example is brilliant, for me. I’ve written and created some things sort of like this ^1 ^2.
Thanks for sharing your works - it’s so squarely in my alley. I’ll look forward to taking a closer look this weekend :)
Every program is a counter of sorts ;)
They’re very brief works, so probably not worth the time! I wonder how many more people there are out there doing stuff like this. E.g. I found Pimalaya, when I had started creating my own comparable thing, for a headless Pomodoro timer.
Haha, that is both comfortably and uncomfortably true, about counters.
I find it a bit funny that this relatively new lisp system contains features that are quite a bit harder to use in Common Lisp
Like what?
Work-stealing scheduling with message passing between processes
Why would it be funny for a system to take features from Common Lisp and attempt to make them easier to use? I’ve read and reread your comments and still I’m puzzled
These are not features in Common Lisp. You’d have to implement them yourself or use a library.