An Exploration of SBCL Internals (2020)
simonsafar.com
simonsafar.com
> I recently decided to leave my current full-time job, and I’ll be working on CCL again. […] I’ll be able to work about half-time on an ARM64 port. Please write me privately if you want to talk about supporting that ARM64 work.
> I've worked on CCL for quite a few years, and I did the 32-bit x86 port, so I have experience in this area. I’m not as good a hacker as Gary Byers, but then again, few people are.
rme
https://lists.clozure.com/pipermail/openmcl-devel/2024-April...
The macro narrative is worse in Erlang; but Lisp isn't perfect either in other ways.
The point is, I net out staying on the BEAM. What I like about Lisp is that I think it's a tool that will serve you for the rest of your career, even if you don't use it for production. That's a pretty cool proposition and maybe one day I'll get there. Emacs is a similar tool.
- can't install libraries from the REPL while working on your program
- can't "compile this function" with a keystroke (I did find "send region/line/buffer to REPL" which is different, or "reload module")…
- … and get type errors and warnings
- can't get an interactive debugger on an error, go to the bogus line (while keeping the debugger), fix the function, compile it, switch back to the debugger, resume execution from any point in the stack. I only found out IEx.pry which is useful and all, but looks like Python's ipdb break point.
- lack of little useful editor commands, at least in the Emacs modes I tried like "write this function in the REPL", "eval and print the last expression". I struggled to have the "go to definition" feature but that depends on the IDE I suppose. The Emacs modes are not in good shape :S
- no cross-references? doubting. And maybe other small things only about the REPL, didn't find my notes.
differences of runtimes are also at play here, but I still find it interesting to compare the REPL experience, I'll welcome more comparisons.
You can get relatively close by putting your application into processes and keep them in a collection or registry, then when you've found an issue and changed the code in your editor you can run recompile and relaunch affected processes. You'd lose a subtree in the application, and hence in-memory storage tightly coupled to those processes, but I find it rather easy to do it this way. Often you'll put in-memory data in separate caching processes and that reduces friction in restarting processes with application logic even more.
The 'let it crash'-foundation of the BEAM system isn't exactly tailored towards trapping and recovering from errors but if you really want to you could probably implement something like that with try/rescue but I suspect it would turn out quite obtuse compared to the CL mechanics.
Shouldn't that say bits? As 8 bytes would be the whole thing ayways.
SBCL is great to poke around in and the decompiler’s great. Also check out ABCL, ECL for what compilation to JVM bytecode and C looks like.
https://simon.peytonjones.org/slpj-book-1987/
These compilers were pulling heroic data structure optimization stunts in 1985, that no modern production compiler for major compiled languages can replicate in 2024.
https://dev.epicgames.com/documentation/en-us/uefn/verse-lan...
The language seems sort of complicated for the domain (gameplay scripting).
University founders Andrew Carnegie, Andrew Mellon, and Richard Mellon are best known for their work in the steel industry and banking.
remember that we're on x86 here, which is a big-endian architecture
While I wish this were true, x86 is little-endian.Thanks for catching it, fixed!
One could have designed OOP like frontends to this fairly easily, and I'm sure there are existing ones. How did Java and C++ take over?
I know there are lots of other ways to work with SBCL, but they are either second-class citizens or paid.
https://susam.net/lisp-in-vim.html
Not 2nd class and I can use it mostly on mac; linux and windows (linux side)are ok. All good.
Alternatively try geany-lisp[1], it was created specifically for those with emacs phobia. There are probably some sharp corners using it, so feel free to file issues if you run into any. It should work with Geany 1.26-1.38; when posting this, I just noticed that there is now a Geany 2.0; I'm assuming the major version bump broke plugins so it may not work anymore.
Neither ends in a working development environment or even text editor.
Compare this to learning Python or Javascript or the C family. VSCode or even just your standard OS text editor is all you need. You can decide to start learning, find a tutorial on Youtube, and execute your hello world in 60-120 seconds.
What I'm complaining about is that it's much harder to "check it out" than it perhaps could be.
At one point many years ago, I wanted to check out this new Python thing. It was so easy, I've been hooked ever since.
I can't argue with that. It did take me a long time to get comfortable with Lisp. But I felt it was worth the efforts.
IDLE is a underrated feature of Python. The default install includes a barebones IDE together with the REPL, making setup for beginners nearly zero effort. On the other hand, in lisp land, step 0 to learn most lisps is to learn emacs beforehand.
Also, knowning CL makes learning Elisp a breeze, so you can customize your editor like nothing else.
It has a lot of other goodies like : Org, Magit etc which makes it worth while.
Portacle, https://portacle.github.io/ , is a way around config and whatnot, lowering the threshold a little.
This is what I stick at the top of my Lisp files when dabbling.
(defun l ()
(load "file.lisp"))
(defun e ()
(ext:shell "vi file.lisp"))
And then I just muddle my way through with a (e) and (l) cycle. Since I tend to not work on 10,000 line files -- this works fine (my files are < 5K lines). More than fast enough, and I get to retain any work variables within the image (plus my command history). It's quite effective really. (print...) debugging works because you can run your code at whatever granularity you like (and you can always refactor it to a finer grain if you want). Don't doubt it until you try it. Turn around is very fast.That said, I discovered that for some reason, firing off something as simple as "vi file.lisp" from SBCL is stupifyingly complicated. I made several 10s google searches and 5s GPT attempts to make that work, but gave up.
So, can't say I can recommend that style of development in SBCL unless someone is willing to chime in with the, apparently, paragraph of code necessary to launch vi on a file.
(require 'uiop)
(defun c ()
(uiop:run-program '("emacs" "-nw" "file.lisp")
:output :interactive
:input :interactive))
EDIT: note that SBCL comes with UIOP included by default, but if you want to use SBCL's implementation-specific facility, it's only slightly different: (defun c ()
(sb-ext:run-program "/usr/bin/emacs"
'("-nw" "file.lisp")
:input t
:output t))I have the same problem with Hylang.
C++ took over by adding OO to C with zero cost abstractions, and then evolving into modern C++ (which discourages OO and encourages composition via template instantiation) without leaving programs behind.
Lisp has supported composition forever (it is one of the big advantages of functional programming), and the macro language is similar to templates. I think the big problem is that it is difficult to scale lisp projects with inexperienced developers (loses to java) and is not zero cost (has a GC, is often interpreted; loses to c, c++ and now rust).
Every competitive Common Lisp implementation has compilation. SBCL defaults to not even using an interpreter for eval.
Few years ago there was work to fix the evaluator and now EVAL has limited evaluation back.
i think scalability problem is a bit overstated. the biggest issue with lisp becoming popular is that it doesn't have a large user base and is not a new language like rust. however despite being old, common lisp /still/ has so many 'novel' things in it that in metrics of programmer ergonomics and programming user interface make common lisp a big winner for me.
as regards zero cost, lisp programs can be made arbitrarily close to being zero cost, but here be deamons.
First, it implies lots of people are paid to learn it. Second, it implies companies will have to invest in adding/fixing support libraries.
Could you elaborate this part?
edit: Once you get the idea of a running Lisp image and you are updating the image it's a game changer. You are not writing a program, then compiling it and then running it anymore (even though those steps happen seamlessly).
Also Smalltalk.
https://lists.cuis.st/mailman/archives/cuis-dev/2023-August/...
save-image
and you can restore that image using ./factor -i=path-to-image
This image workflow and interaction via the inspector provides a very similar workflow experience to both Smalltalk and Common Lisp.
PS: You can also do copy and paste :)
The only thing I heard about this is Paul Graham's story on fixing particular bug in viaweb while talking to the user, but that's just one story from 90s. Would be great to hear more with regard to more modern setup.
However, if I know my history correctly, Smalltalk and Common Lisp implementations were generally not cheap. Objective-C was largely tied to NeXT, which required buying into a niche ecosystem. Dylan was a casualty of Apple’s mid-1990s business struggles.
C++ benefitted from inexpensive implementations from vendors such as Borland and Microsoft, and it also benefitted from its close relationship with C, which already gained a foothold in the 1980s.
Java benefitted not only from Sun’s marketing machine, but also from its free compiler and runtime from Sun. Java overtook Smalltalk, despite the fact that Java lacks Smalltalk’s dynamics.
I think had there been solid cheap or free Smalltalk and Common Lisp implementations around 1992, Java wouldn’t have gained a foothold, though C++ would have still been very appealing to C developers, though perhaps if Objective-C were more broadly available to non-NeXT developers, it would’ve been a formidable competitor to C++ in terms of providing a “C with objects” environment.
100% agree. i think it is also interesting that in comparison to before lisp community of today is so supportive of free software, standing more on the left wing of the open source community.
My favourite quote from some other participants was "he didn't see us at lunch not because AI Lab culture died, but because we avoided him"
I imagine that’s ticking the boxes for most of their users, and they’re not in the endless “security update” treadmill.
2012 Allegro CL 9.0
2015 Allegro CL 10.0
2017 Allegro CL 10.1
2024 Allegro CL 11.0
2012 LispWorks 6.1
2012 LispWorks 6.1.1
2015 LispWorks 7.0
2017 LispWorks 7.1
2018 LispWorks 7.1.1
2019 LispWorks 7.1.2
2021 Lispworks 8.0
2022 LispWorks 8.0.1
Looks similar to me. LispWorks also had patch releases in between. Both are on the market for more than 35 years. Both are mostly written with CLOS and thus are especially to update with patches, additionally to the usual ways to update code (-> late binding). One just loads patches (which are mostly compiled Lisp code) into a running Lisp and that's it. Alternatively one can save a new image with patches loaded.When one needs a patch or a feature, one would typically contact them directly. Both provide patches to the users.
Franz has made that simple for the user, they have a relatively continuously stream of patches, one can call an update function and it gets the necessary patches and installs them.
SBCL has monthly (!) releases, where the user (that's what I do) would typically compile it from scratch using the supplied sources. Updating is quick, around a minute for a recompile.
GNU Common Lisp (https://www.gnu.org/software/gcl/) seems to have existed in various forms from the mid 1980s, but it was probably outclassed by the contemporary big tech companies.
All the Lisp implementations needed more memory than C programs would, which limited their impact before 32 bit machines became standard. And by that time, C was strongly in place.
In comparison, ECL which forked from the same family seems to work out much better over time.
We've been fooled in 90s so easily!
The killer "like C++" feature that made adoption easy was the "C/C++ like syntax, with braces and everything".
LISP feels like both an "assembly language" and a "higher level language" at the same time. It's excellent for solving unusual problems, but it carries a lot of baggage when aiming for "usual" problems.