One year progress update Schemacs (formerly Gypsum)
Ramin Honary (he/him) - Pronunciation: "Rah-mean" (hard-H) "Ho-na-ree", Mastodon (preferred): ; blog: https://tilde.town/~ramin_hal9001; Codeberg: https://codeberg.org/ramin_hal9001/schemacs - SourceHut: https://sr.ht/~ramin_hal9001
Format: 24-min talk ; Q&A: BigBlueButton conference room Etherpad: https://pad.emacsconf.org/2025-schemacs
Etherpad: https://pad.emacsconf.org/2025-schemacs
Status: TO_REVIEW_QA
Talk
Duration: 23:14 minutes02:07.200 The scope of the project 04:24.760 Difference with Robin Templeton's project (Guile-Emacs) 05:49.720 Progress made since last year 07:28.040 Portable React-like GUI 09:06.040 Demo 11:48.700 Additional changes 14:12.020 Other Scheme implementations 17:06.200 GUI framework 21:51.520 Wrapping up
Q&A
Description
During EmacsConf 2024 last year I presented my work on a clone of GNU Emacs written in Scheme which also clones the Emacs Lisp programming language. In this talk, I will briefly present an overview of the project similar to the talk I gave last year, and then discuss the progress that I have made on this project in the past year.
To quote the description from the presentation I gave last year:
Unlike other editors which only clone the Emacs keybindings (Edwin, Jed, jEdit, Jove, Lem, MG, Yi, Zile), I hope my Emacs clone will also fully clone the Emacs Lisp programming language well enough that many of the packages in ELPA, Non-GNU ELPA, and perhaps even MELPA, can be used in [Schemacs, formerly "Gypsum"] without any modification. I would also like to talk a little bit about how I am implementing it (the software architecture), and invite others to contribute.
I think my project is of interest to many Emacs users because, firstly, I have personally spoken with a relatively large number of people who have expressed interest in making Emacs programmable in Scheme. Secondly, there is a good amount of prior art for Scheme implementations of Emacs. There are even builds of Emacs that link to Guile which provides a "scheme-eval" built-in function that translates between Elisp data types and Scheme data types. The Guile compiler itself ships with an Emacs Lisp compiler as well, although it does not provide enough of Emacs's built-in functions to be of much use.
The progress I have made so far:
Ported all Guile-specific parts of the Emacs Lisp interpreter to fully standards-compliant R7RS Scheme code. The interpreter now runs on a few different Scheme implementations, not just Guile. The GUI remains Guile-only for now.
Implemented a new R7RS-compliant lexer and parser which constructs an Abstract Syntax Tree (AST) data structure, making it easier to find the source of errors and produce informative back traces.
Implemented enough of the Emacs Lisp interpreter to be able to load the "subr.el" source file, this defines what you might call the "core" of the Emacs Lisp language, including macros such as "defun" and "lambda."
My primary goal continues to be to make it as easy as possible for other people to contribute to this project. Pretty soon it should be possible to run the Emacs Regression Test suite (ERT) in the cloned Emacs Lisp interpreter. Once this is done, we can run the same test code used during the building and testing GNU Emacs to test Schemacs. Hopefilly then, anyone will be able to select a failing test, write code to make the test pass, and submit a patch.
About the speaker:
I am Ramin Honary, I am have been professional software engineer for 17 years and I have always had a passion for functional programming languages, especially Haskell and the Lisp family of languages.
Transcript
Hi, EmacsConf 2025. My name is Ramin Honary, and I'd like to talk to you today about my project called Schemacs which I presented last year. Back then it was called "Gypsum" and the name has since changed. So my name is Ramin Honary. I'm an Emacs enthusiast, have been since 2017 or so. I'm a full stack software developer. I love Haskell, Scheme, anything functional programming related, and of course Emacs. I started learning Scheme about three years ago, and this is my third time presenting at EmacsConf. So the Schemacs project that I'm talking to, I'm talking about to you today, was originally called "Gypsum". The reason I did not call it "Schemacs" was that the name "Schemacs" was taken on GitHub. But in the past year, I was able to get the permission of the author of GitHub's Schemacs project to name my project the same thing, even though it's a very similar project. So I changed the name. Let me see if I can quickly show the screen. So yeah, I have archived the old project. It's still there, but there's an explanation in the readme file and a screen grab of the conversation I had with the original author of GitHub Schemacs. My Schemacs is not on GitHub at all. It's only on Codeberg. So please don't get confused. But yes, I received permission to change the name and so I did. And I would like to give a quick shout-out to user "Tusharhero" for helping me with that. This person really helped make that name change happen. So back to the slides.Captioner: sachac
Q&A transcript (unedited)
[oops, forgot to start] object protocol has a scheme implementation. Does this mean schemacs will be meta object changeable in practice? So I don't actually need the meta object protocol so far. In the reference implementation for Guile, Guile has its own object-oriented system called Goops. I'm sorry, I'm hearing a delay. Anyway, I'm going to turn off my stream quick. There we go. So, um. Yes, uh, I, I don't I wasn't aware of the, um. the meta-object protocol that you have mentioned here, but I will look into it. I know that there isn't really a standard meta-object protocol for Scheme. That was an issue for me because I'm trying to make this cross-platform, and so I've done all of my work so far without a meta-object protocol because that's the easiest way to make it work on multiple Scheme implementations. But if there is a nice portable one that works on many implementations, I would use that, yes. It's just that so far it hasn't been necessary. I've been doing mostly functional reactive programming and React.js-like framework. I've created that for the GUI front end. And that's all the more I've needed so far. So, yeah. Oh, yeah, please, next question. Sure. So how will the GUI display code be R7RS compliant? As far as I know, there's no DL open in R7RS. That's right. Yeah, R7RS small is extremely small and does not have any features at all. But it does provide a conv expand macro. And this allows you to load in different code depending on which scheme implementation you're using. So basically, I'll have to write a different back end for each scheme implementation. And I think that's really the only way is possible at all, because there's no standardization. So essentially, the libraries that I've written for schemacs will become kind of a platform-independent way of writing GUIs for Scheme. It's just a matter of, will your Scheme implementation support the Schemacs GUI protocol? So I've kind of written my own protocol, and it's entirely R7 RSML compliant. It's all done with record, what are they called, record types. Do you think some of the Schemacs could be extracted into SFRIs since you've made it portable between scheme implementations? Yes, I would definitely like to do that. Probably first thing I'll do is start splitting up and publishing independent libraries on the Aku package manager. This is a kind of a package manager ecosystem for Scheme, and in particular R7RS Scheme. And it's also mirrored on the other package manager, Snowfort, just by the way. But yeah, and then I might be also, I've considered creating a SRFI for the lens library, which is based on the Haskell lens library. I don't think that exists yet in Scheme, so I thought that might make a good SRFI. Is there a recommended Scheme implementation? Guile is the reference implementation. It's the only one that works with GUI, but as I demonstrated in my presentation, the Emacs Lisp interpreter works on multiple schemes so far, and I've had trouble with some of the scheme compilers. But yeah, I would recommend Guile. But how would schemacs deal with Emacs's re-display architecture will be having its own display architecture? And if so, how will you handle things like overlays and images? Yeah, definitely. That's to be determined. So basically, the scheme way of doing things So, I've created this React-like programming framework. It's like ReactJS or Vue.js. That is just the API of how you write GUI code in Scheme. And each Scheme implementation will have its own GUI backend, which implements that Protocol. And so when it comes time to link the Emacs Lisp built-in functions that do these things like overlays and so on, we're going to have to come up with some way of modeling that using the scheme framework that I've designed. And I may have to make alterations specifically to support Emacs Lisp. I don't know yet. I haven't got that far. You were saying that you would like to get the most out of the 1300 and something Emacs packages that exist. Are there technical blockers to doing them all or just a problem of getting enough people to jump into it? Yeah, it's just a matter of implementing enough of the Emacs built-in functions. Right now, there's kind of a big bug. I mentioned this also in the presentation. The stacks trace that you saw during my presentation, that is the biggest bug right now that's preventing me from running most other code. And I don't think other people will be able to contribute to the code base until I get that bug fixed, because it doesn't capture closures correctly. it doesn't behave like Emacs Lisp does, and that's the big problem. So once I get that worked out, then it's just a matter of implementing enough of the EmacsLisp built-in functions, these are the functions that are mostly implemented in C, implementing those in Scheme. And that, yeah, that's the thing that I'm going to need a lot of help with because there's quite a few of those APIs. But I imagine, I have no idea, no way of knowing, but I imagine we don't need 100% of them in order to run most of Elpa. We probably can get some of the important large Elpa packages like Magit and Org mode with just enough of the Emacs Lisp built-in functions to handle that. But we won't really know until we've tried. So yeah, I'll try to get this bug fixed right away. That way we can all start working on it together, hopefully. Highly relatable answer there. We'll burn that bridge when we're on it or something. What are your thoughts on chicken scheme? Will that be a good fit? Do you think? I think it will be, um, I, I did show trying to run chicken scheme in my, um, presentation and, uh, I ran up against some kind of issue, which I really don't know how to debug. Um, it's probably something to do with the, uh, pattern matcher. Um, I'm using the pattern matcher, uh, written by Alex shin, which seems to be the most portable. Pattern matcher, uh, for our seven RS scheme. But not all scheme compilers implement, what is it called? The macro, I can't remember what it's called. There's the macro expansion system for R7 RS small. All of these scheme implementations seem to have a slightly different take on how they work. And so that macro expander has been, for pattern matching, has been the biggest difficulty in making this code portable. And so I'm thinking of ways of maybe trying to ditch pattern matching, but that's such a useful feature and it's hard. So I don't know, we'll see if I can, if somebody can help me get it to work on chicken team, I'd really appreciate it. Can this implementation be used by Guile's Emacs Lisp mode? Guile's Emacs list mode. Okay. Yeah, good question. I did mention this last year in my presentation. Emacs list in Guile is totally different from what I've done. That implementation was written about 10 or 15 years ago. I can't remember exactly when. It is quite incomplete. I don't think it even runs most of the macro expanding code. Some of the code that is written for GNU Emacs in Emacs Lisp, where GNU Emacs is initializing itself, it can't even get the first file in that code. It hasn't been touched in 10 or 15 years. Initially, when I first started this project, I was using the parser for Guile's Emacs Lisp implementation, but it didn't give me things like source locations, so I had to rewrite that. And also, it wasn't portable. So yeah, because I want it to be portable, it's necessarily going to be not reliant on anything that's inside of the Guile library, including the Emacs LISP interpreter that's there. Maybe I could replace the Emacs LISP interpreter in Guile if Andy Wingo would be interested. All right. And I see we've got a few people that did jump into the BBB. I'm just going to quickly, oops. quickly try to make my text a little bigger so I can read a question that came here. I wonder if we can do some sort of pragmatic analysis on popular Emacs packages to see what list of functions they tend to depend on while a function calls down to the lower level. Yeah, that would be good. Somebody please do that for me. Awesome. Somebody's raising their hand. Divya. Let's see. Yeah, can you hear me? Yes, I can. Yeah, go ahead. Hello, thank you. Yeah, this is really awesome. I use Guile, and I love Guile, and I also love functional programming, so this is really nice that you took the declarative approach. One thing that I'm interested in is, are you also considering Racket in the scheme group? Because I know a lot of people do not consider Racket as a sort of scheme thing, because it grew out of it. Do you think you'll take something from Racket? Because I think Racket has a lot of good ideas that can be used. Yeah, I briefly looked at Racket's GUI library, but it's very, very heavily dependent on Racket's macro expander, which is, well, yeah, the macro expander is extremely complex for Racket, and I don't think it's possible to port it to any other scheme, as far as I know. But Racket is based on SheaScheme. And I am making an effort to port my code to Shea's scheme. I mentioned this earlier, but there's the Gwen Weinholdt Aku system, which allows you to translate R7RS to R6RS. And since Shea is an R6RS compiler, I did at one point get the Emacs Lisp interpreter to compile for Shea, although I think There's been a change either to Aku or somewhere in my own code base. It doesn't build anymore, and I'm not sure why. But I would also very much like to run this on Che. And I guess in that sense, we'll be able to work on Racket as well. There's also one other option. Alexis King has written an R7RS language package for Racket. I have not yet tried. running my package on R7RS for Racket. But that would be something interesting. Yes, I would like to try that. Yeah, it'll be interesting. I do have some experience with chairs. So, uh, if I can find some time, I'll, I'll, I'll certainly like to, I would appreciate. Yes. Yeah. Go ahead. Yeah. Another question I have is, like, what exactly is sort of, like, the, the approach is that you'll 1st want to do the interpreter and then have enough list functions. Uh, getting the max list functions interpreted or interpretable. And then go for GUI or do you want to sort of like go hand in hand is like we have the interpreter working on and we have also the GUI and we sort of use one for the other. Yeah, I consider the two tasks to be parallel. So I'm actually doing the GUI separately. The reason why is because the GUI for Schemacs is really just a clone of the look and feel of Emacs. It's not like an actual clone of the low-level C code that puts everything on screen. And I'm actually not really that interested in the low-level details of how Emacs draws things on screen either. I think it has a lot of historical baggage, and I'm actually trying to move away from that. So that was part of the reason why I started with this React.js or Vue.js-like Reactive GUI framework. So that GUI part is completely separate. And I want to worry about the details of how we make the GUI look and feel similar in Schemacs, similar to GNU Emacs. In Schemacs, using the Emacs programming language, I think that's something that we should worried about after we have enough of the Emacs list implemented. Yeah, that makes sense. There are sort of, I'm a bit worried. So, I don't know if, so one of my presentations is going to be tomorrow. I'm working on something called Emacs Viewer. It's a document viewer in Emacs. And essentially one of the issues that I'm up against is that Emacs's display system is sort of very let's say, not flexible. When trying to analyze where this inflexibility comes from, I don't think it's just the display architecture. I think parts of eLISP itself are connected to the display architecture. The notion of a cell in a buffer, itself is connected tightly to how the re-display architecture works. So I think you'll have to sort of figure out what exactly you can salvage from ELISP without taking the display architecture baggage. That's right. I do anticipate that's going to be fairly challenging. It's all Turing-complete, so I imagine we're probably going to end up creating something like an emulator for the Emacs Lisp display architecture in Scheme that will somehow translate down to the React-like protocol that I've written. But yeah, I don't I haven't that's nice. No, this is this is very exciting. Yeah. Oh Yes, it is. Yeah, I'm glad so like a lot of people have told me that they really Are excited to see this project and this really helps me You know keep focused on this project because a lot of people are very interested. So It's so I'd like to move on to a couple of questions from the past. We're starting to build up a good backlog. Thank you for that. Yeah Next question from the pad I have. Can you tell us more about the show stopping bug? How to squash it? How can people help? OK, well, that one, unfortunately, I think, unless you're really a scheme genius and you can really read my code and immediately understand how it all works, I don't think you'd be able to help. It shouldn't be too difficult for me to fix. So it has to do with how closures work. And a closure is basically an object that can be created with stuff that's on the stack. And this is a feature, I think, that was introduced with Emacs 27. I can't remember exactly, but it's actually a relatively recent feature. It was ever since they introduced lexically scoped variable bindings in Emacs Lisp. And so yeah, the problem is that when you create like a let structure and you could declare a variable in the let. And then you create inside of that a second let structure, and you have a lambda inside of that. And the lambda references or uses a variable that was declared in the outer let binding. That outer let binding is somewhere on the stack. And the lambda you can actually return it as a value. So when you do return that lambda, it has to have a note somewhere inside that says, by the way, I'm using that variable. So you need to capture it and restore it to the stack whenever this lambda is applied, whenever you execute it. And that is where the error is. It's not capturing the stack variable properly. And I think what I'm going to do, I haven't looked into it in detail yet because I've gone back to GUI stuff recently, but what I'm going to do, I think, is just do a static analysis of the code inside of the Lambda and see which symbols are being used, and then just capture all of those and place those into the record type that stores the lambda. That's how I'm going to fix that, I think. I hope anyway that's going to work. You never know with bugs. They're always a little bit tricky. Okay, next question. Are there performance concerns with implementing certain C primitives in PeerScheme? So who is it? The famous computer scientist that said premature optimization is the root of all evil. I think it was the guy who invented the A star algorithm. His name escapes me at the minute. But yeah, I'm not concerned about performance yet, although most of the scheme compilers that I have seen, especially Shea and Gambit have extremely good performance characteristics. And so I think there won't be too much difficulty with performance, even implementing some of the C stuff. And besides, a lot of the GUI stuff is already written in C anyway. I mean, it would be cool if we had a scheme GUI library that painted to a canvas, maybe for a Wayland implementation or something. But I don't know. It's not a concern for me, performance. Okay, there are a few more questions. I do want to mention that the stream has cut away at this point, but we're still recording live. All of this will be put up on the website and so on like that. So, I appreciate all the enthusiastic questions and you're kind of tanking through them all. Me too. I love how many questions I'm getting. This is very encouraging and it really makes me want to keep on working on it. So it's great. I'm so glad to hear that because that's exactly the message I think you should be receiving. This is a fantastic project. Thank you so much. I'll just say so myself. If the project is successful, are you worried about a possible split in the community between Schemacs and GNU Emacs? Oh, I have thought about that. And I really don't know what's going to happen. There seems to be already a huge demand for a scheme-based, a modern scheme-based editor. You know, the Edwin scheme for MIT scheme hasn't been touched since like 1987 or something, maybe 1993 or, but anyway. There seems to be huge demand. And so I guess a lot of people who are currently using GNU Emacs will probably just switch over because they've been wanting something like this for a very long time. And then, I mean, is that going to cause fragmentation? Is it really a big deal, though? I mean, it's all GPL-licensed code. I mean, I think a rising tide raises all the ships at the same time. So, yeah, also, the last thing I want to say about that is I would like to contribute some of what I do in Schemacs back into GNU Emacs, if I can. So, for example, I'm going to be working on like a canvas library where you can have interactive canvases and you know you can actually like draw pictures and put things with the mouse and drag things around. And I was thinking you know if if I can figure out how that works maybe I can write something like that for Emacs or GNU Emacs using the Cairo library, you know, SVG rendering library that they have. So, you know, if I have time, I would like to continue contributing to GNU Emacs as well. I'm sorry, what was the name of the library you mentioned? Oh, Cairo, like Cairo. Oh, Cairo, yeah. Absolutely. I spelled that poorly. The dream of never needing to change to the web browser. Would schemacs bring us closer to that? I hope so. That's also a dream of mine. The part of the reason why I wanted to work, you know, make sure I had a really good workable GUI framework is so that I could, you know, we could write apps like, you know, they have a mastodon client written in Emacs Lisp. that would be so nice to have this, you know, a really nice Mastodon client that was right inside of, you know, our scheme environment where we were doing our text editing and other stuff. I've always wanted something like that, or it would be cool to have just a slightly nicer GUI for Magit. So, yeah, I mean, like, yeah, being able to avoid the web entirely and just be able to like, you know, do social networking and do your GitHub stuff, everything from within Emacs or Schemacs in this case, that's a dream of mine as well. And so I hope that that's where we end up in a couple of years. The sooner the better. Anything, just double checking. Anything specific other than minimalism that made you choose Scheme over Commonwealth? Oh, yeah, it's kind of a philosophical question. So a couple of things. First of all, it was a conversation I had with William Byrd, and he's a guy who makes the Mini Conran framework for Scheme. It was his PhD thesis. He worked with, I'm sorry, I just can't remember his name. He worked at the University of Indiana. Another famous Scheme or Lisp person was there. Friedman, Dan Friedman was his advisor. Yeah, big name in Lisp. Anyway, so I was talking with William Byrd, and I'm a huge Haskell fan, and he told me why he didn't like Haskell at all, and kind of convinced me to try Scheme out. And what I really like about Scheme is, yeah, like you said, the minimalism, but it's more that it is very close to the mathematical framework of lambda calculus. Haskell is probably the most pure lambda calculus that I've ever used, but Scheme is like the simply typed lambda calculus, and That just appeals to me. I think, you know, if you have this tiny, tiny core language from which all of the computing can be defined, I think it's kind of a shame that so far we just haven't explored that space yet. I mean, there's compared to JavaScript or Python, there's very little scheme code out there and it could be doing so much. And I would just like to try and expand the scheme ecosystem and see just what this tiny little language can do. And I think we haven't even seen a fraction of what it can do. That's why I've chosen scheme. Divya, I see you've got a bunch more comments. I think we're just about close to our time here, but if you wanted to jump back in, I'm sorry, I had to cut you off a little before. No, it's fine. No, it's fine. I think I agree with most of what he said. So, yeah, thank you so much. Um, closing thoughts, Ramin. Yeah, I guess everybody, please, if you're interested, keep watching my Mastodon and keep watching my Codeberg. I'm going to try and squash this bug as quickly as I can. I hope early next year, hopefully not much later than February, I'll actually be able to start taking in contributions for some of the Emacs Lisp built-ins in the code base. So, please keep watching. The pace of my development has increased pretty rapidly recently, and I think we're pretty close to getting something that we can all use together. Thank you once again for your amazing talk, for your exceptional work, and for jumping in, doing the live Q&A, rolling with us here as we have yet another We'll See How It Goes conference. It's been just amazing so far, and this talk is no small part of that. Thank you. Oh, thank you so much. Yeah. OK, cool. And thanks for all the questions, everyone.Questions or comments? Please e-mail emacsconf-org-private@gnu.org
