Steel Bank Common Lisp version 2.6.7
sbcl.org
sbcl.org
Namely, that "SB" stands for "Sanely Bootstrappable" - something that the CMU Common Lisp was unable to do
The difference with SBCL is that it can compile so long as you have any CL implementation that handles certain broad, but not complete, subset of ANSI CL.
It does it by being able to compile itself in sort-of sandboxed state hosted within another CL image, and then using that compiler to build itself, without requiring to modify the host compiler like CMU
As for the bytecode, as far as I recall CMU CL did not have bytecode compiler at all - it had evaluator option, which was indeed dropped for a long time from SBCL but was recently reintroduced, partially to support efforts such as porting Kandria [1] to Nintendo Switch
The byte code compilation option is described in CMUCL documentation, section 5.9 Byte Coded Compilation: https://cmucl.org/docs/cmu-user/html/Byte-Coded-Compilation....
That said, as mentioned, it gave no real impact on bootstrappability nor portability
* the SB-SIMD contrib now supports ARM64. (Thanks to Sylvia Harrington)
* AVX512 instructions are now supported on X86-64. (Thanks to Robert Smith and Arthur Miller)
* additional support for SIMD instructions on ARM64 and X86-64. (Thanks to Arthur Miller)
These seem like pretty awesome additions. Does anyone know how SIMD works in SBCL? Is this at the codegen layer? i.e. can it auto-vectorize or anything like that? Or are these intrinsics you have to explicitly ask for?This is the first news I've seen on HN in weeks that I am genuinely excited about! I have several AVX-2 hobby projects in Common Lisp, and an AVX-512 machine. It's an unexpected surprise to read this morning that this very useful ISA is suddenly unlocked. I'll be trying it out right away.
(edit: Looks like they mean *compiler* support for AVX-512, but not SB-SIMD definitions (yet). So I believe the only way for end-users to call AVX-512 instructions right now is to write custom VOP's).
> "Or are these intrinsics you have to explicitly ask for?"
There are language SIMD types and you explicitly use SIMD functions that operate on them. I believe it's essentially the same idea as C intrinsics. You can for example write (interactively)
(u32.8+ (make-u32.8 0 1 2 3 4 5 6 7)
(u32.8 10))
;; => #<SB-EXT:SIMD-PACK-256 10 11 12 13 14 15 16 17>
And that's VPADDD under the hood. Or reading an array (loop with sum = (f32.8 0.0f0)
for index below (* 8 (floor length 8)) by 8
do (setq sum (f32.8+ (f32.8-aref array index)
sum))
finally (return sum))
which compiles down to a small loop around the vector insts VMOVUPS YMM1, [RDX+RCX*2+1]
VADDPS YMM0, YMM1, YMM0
I much prefer it to writing intrinsics in C (and the results are just as good). It's an interactive, exploratory, coding: I write small modular functions, SBCL compiles them on the fly, I glue them together with high-level language constructs.Same here, but in Julia instead. Sometimes I drop down to LLVM intrinsics (e.g. to force lop3.lut on GPUs).
Nice to hear! :)
It is the basic compiler support, and lots of instructions added. However, you can't use knor, knoq and similar since they require scheduling of k-masks. Not done yet. But you can certainly use some of avx512 instructions and add yourself if you need some that is not available already. Check https://github.com/sbcl/sbcl/blob/master/src/compiler/x86-64....
On implementation level, it is a codegen layer. It uses a system of macros to generate instructions from a database of instructions. The database is specified manually:
https://github.com/sbcl/sbcl/tree/master/contrib/sb-simd/cod...
At compile-time, they are converted into "VOPs", i.e. intrinsic functions, which are used by the compiler to emit the actual machine instructions.
> can it auto-vectorize or anything like that?
Unfortunately, it can't.
> are these intrinsics you have to explicitly ask for?
Yes, more like higher-level intrinsics. You get quite some automation, but you are requesting manually what you need. More like a DSL, than pure intrinsics. This is how you can use it (as an example):
(defun count-lines-and-words-ascii (sap size ws-init-state) (declare (type fixnum size) (type (unsigned-byte 8) ws-init-state) (type sb-sys:system-area-pointer sap) (optimize (speed 3) (safety 0))) (loop with loop-end of-type fixnum = (logandc2 size 127) for i of-type fixnum from 0 below loop-end by 128
with 0x0 of-type u8.32 = (u8.32 #x00)
with 0x20 of-type u8.32 = (u8.32 #x20)
with 0x0A of-type u8.32 = (u8.32 #x0A)
with wa of-type u64.4 = (u64.4 0)
with la of-type u64.4 = (u64.4 0)
with ws-prev of-type u8.32 = (u8.32 ws-init-state)
for c1 = (u8.32-sap-ref sap (+ i 0))
for c2 = (u8.32-sap-ref sap (+ i 32))
for c3 = (u8.32-sap-ref sap (+ i 64))
for c4 = (u8.32-sap-ref sap (+ i 96))
do
(flet ((process-chunk (curr prev)
(let* ((ctrl (u8.32-sat- (u8.32- curr 9) 4))
(ws (u8.32-or (u8.32= ctrl 0x0) (u8.32= curr 0x20)))
(ws-shift (u8.32-alignr ws (u8.32-permute128 prev ws #x21) 15))
(wmask (u8.32-andc1 ws ws-shift))
(lmask (u8.32= curr 0x0A)))
(values wmask lmask ws))))
(multiple-value-bind (wm lm prev) (process-chunk c1 ws-prev)
(psetf wa (u64.4+ wa (u8.32-sad wm 0x0))
la (u64.4+ la (u8.32-sad lm 0x0))
ws-prev prev))
(multiple-value-bind (wm lm prev) (process-chunk c2 ws-prev)
(psetf wa (u64.4+ wa (u8.32-sad wm 0x0))
la (u64.4+ la (u8.32-sad lm 0x0))
ws-prev prev))
(multiple-value-bind (wm lm prev) (process-chunk c3 ws-prev)
(psetf wa (u64.4+ wa (u8.32-sad wm 0x0))
la (u64.4+ la (u8.32-sad lm 0x0))
ws-prev prev))
(multiple-value-bind (wm lm prev) (process-chunk c4 ws-prev)
(psetf wa (u64.4+ wa (u8.32-sad wm 0x0))
la (u64.4+ la (u8.32-sad lm 0x0))
ws-prev prev)))
finally
(return
(loop for j from loop-end below size
with words of-type fixnum = (sum-lanes wa)
with lines of-type fixnum = (sum-lanes la)
with prev-ws of-type boolean = (logbitp 31 (u8.32-movemask ws-prev))
with tlines of-type fixnum = 0
with twords of-type fixnum = 0
for byte of-type fixnum = (sb-sys:sap-ref-8 sap j)
for curr-ws of-type boolean = (or (= byte 32) (<= 9 byte 13))
do
(when (= byte 10) (incf tlines))
(when (and (not curr-ws) prev-ws) (incf twords))
(setf prev-ws curr-ws)
finally
(return (values (the fixnum (+ lines tlines))
(the fixnum (+ words twords))
nil))))))https://news.ycombinator.com/item?id=44099006
I discovered this while doing some research for a post the other day: https://vale.rocks/posts/hacker-news
I’m curious: was Arc running Racket BC or CS? I understand it got a big performance boost after switching to Chez Scheme.
dang: It was running BC. I had high hopes for switching to CS because I'd heard the same thing you had, but when I tried it, HN slowed to a crawl. This stuff is so unpredictable.
https://news.ycombinator.com/item?id=47140657I can't remember the details, but I recall that Arc was pinned to an older version of Racket and didn't benefit from improvements to BC and then later to CS.
But ... be aware that the Arc interpreter is much more dynamic than Racket, so in general normal Racket programs are more efficient than Arc programs.
- use SB-VM:NEW-ARENA to make a new arena
- use SB-VM:WITH-ARENA to redirect ordinary allocation into an existing arena like you would use WITH-OPEN-FILE or similar macros
The only real doc is this internals note, and it doesn't even cover NEW-ARENA which I guess is left as an exercise to the reader: https://github.com/sbcl/sbcl/blob/master/doc/internals-notes...
Personally I think/hope they would have earlier discoveries / more broad usage of the deterministic systems like nix etc, which are built upon functional principles of immutability etc.
Maybe the world would be guix/Hurd!
Yeah, that, uh, doesn't sound like Lisp
To me the mythology of lisp (from my mostly outsider perspective) is more like "make everything a interoperable DSL" (although if this is what you were describing with your sentence then thats fair enough)
So while Lisp may not be purely functional, the culture hewed that way.
I specifically remember the breaking point being third-party library where none of the functions had any parameters. Instead, everything was controlled by using dynamic binding to adjust the variables within the functions. Various forum members kept praising its beauty and elegance, but I found it needlessly confusing.
I have a soft spot for the Lisp family of languages. I've been using Emacs for almost thirty years and have used both Scheme and Clojure in production. However, my experiences back in 2006 have left me with a permanent bias against Common Lisp.
The use cases for images would be: delivery of applications to users, or (internally) delivery of some fixed set of underlying code that is used as a substrate for development but that wouldn't normally be changed by developers.
Normally, the developer has an image running all day, and does development and testing in it, but (unless needed for additional testing) doesn't save that image as a new binary that others can run.
i would argue that lispers use of mutability was much more surgical and principled but maybe i'm biased
Immutability requires lots of copying and early computers didn't have much memory to spare...
> In addition to the facilities for describing S-functions, there are facilities for using S-functions in programs written as sequences of statements along the lines of FORTRAN (4) or ALGOL (5). These features will not be described in this article
I'm strongly convinced, having used Scheme, CL, Racket, Clojure that Lisp is doomed to be (mostly) a hobby language.
The very power of Lisp, macros, dynamic programming, reflection lead to a mess of an ecosystem where every single developer reinvents the wheel and nobody can understand yet another DSL invented by the next developer next to them.
Racket's theme of being a "programming language for building programming languages" is just the poster child of this naivety: I don't want even more friction.
What scales and works is simple and boring.
That's by the way why also Haskell has struggled forever. Beyond its dreadful DX, poor tooling and unacceptable compilation times, the language is just plagued by compiler extensions and every single developer reinventing its own abstractions.
There was the simple haskell movement to just standardize around a set of extensions and conventions, but nope, these languages unavoidably attract people that want to stay in the ivory tower.
Really, I love both lisps and haskell, but I would take a dreadful php over them every single day at work. No contest.
Says who, you? Wrong. I use Common Lisp at work.
edit: and not just use as in a side toy, design and writing software in CL is my primary responsibility. FWIW, at a FAANG!
Do you work on ITA? Only FAANG I'm aware of using Lisp is Google.
I'm an IC and have three more engineers working alongside, so a very small team.
We don't expect anyone we're hiring to know, understand or have even heard of Lisp :-), just the curiosity and willingness (which we evaluated in the interviews) to grok it when provided enough support and runway to get upto speed.
As you seem to be keen for such a job, the best bet right now is start using SBCL in your daily work. Trick: don't say you're using Lisp just show (the output), don't tell!
Have you like looked at anything in the Clojure ecosystem because this description makes no sense of any kind. Clojure has macros but less powerful than common lisp and Clojure code in the ecosystem tends to be small and understandable.
The "Lisp Curse" is a ridiculous and tired myth that can only be invented by people who have looked at the language for 5 seconds and went straight to finding an excuse to not learn it.
But seriously, I think Clojure has a particularly strong tradition of writing clean, readable code.
Use-cases for code that writes code across a host boundary are rare, yet enormously useful and really difficult to achieve without homoiconic nature of the language.
Hyperfiddle/Electric is a nice project that effectively utilizes the idea.
Have you ever seen GitHub language stats? Elisp there in the list a few points behind Lua, Elixir, OCaml and Haskell. The amount of Emacs Lisp on GitHub alone should be at least surprising. There's so much Elisp in the wild - the amount of it probably exceeds Clojure, CL and Racket combined. And let me remind you that it isn't a "general-purpose PL" - it's meant for one and only purpose.
Look at the number of package for AI-coding in Emacs¹ - 35 and counting. Mind that emacs has no central curated marketplace with the same discoverability as VSCode's. Packages live across MELPA, GNU/NonGNU ELPA, and countless personal repos, so a hand-counted 35 from a Reddit roundup is almost certainly an undercount of what exists in the wild.
And that's just one of the observable axes of Lisp. Anyone can join Clojurians Slack and scroll through #news-and-articles, just out of curiosity. It is hard to find a problem space today or a runtime where Lisp has not proliferated. Why? Because Lisp is enormously practical. Just because you convinced yourself it isn't, doesn't change a thing about reality.
---
¹ https://www.reddit.com/r/emacs/comments/1uwm3c0/the_state_of...
My point stands.
Your point can stand, sit or jump around in a circle - makes no difference. Any ignorant fool can make a hollow point about things they don't fully understand and congratulate themselves in the process.
You can make similar "observation" about Linux on Desktop, mechanical keyboards, 3D printing and Raspberry Pi/Arduino tinkering and call them "hobby business".
You're essentially conflating "niche" with "unserious". By that logic Linux was a hobby OS and Git a hobby VCS - both literally started as one guy's side project, both now run the industry. Lisp is niche, not unserious: Clojure runs Nubank, Walmart, Cisco and Apple; Common Lisp ran ITA/Google Flights; and most of the features in whatever your favorite language is were Lisp ideas first.
The fact that Lisp is the “programmable programming language” doesn't mean that every engineer should be inventing weird versions of while loops. What it does mean is that a skilled Lisp programmer can build a domain-specific language that substantially helps in development.
One good example of this is the Crash Bandicoot games, along with the same studio's Jax and Daxter, which were built with dialects of Lisp (yes, they had to compile the code, and take care with storage allocation, just like any other game code). Cisco hired Kent Dybvig, principal author of the Chez Scheme system, and open-sourced that software; I have no clue what they use it for, to be honest, but I assume that they had some reason for doing this. Companies using various Lisp languages have been documented in areas from fintech to quantum computing.
Not that these people are necessarily bad at their jobs, but they're definitely a personality type you should learn to identify so you can manage them properly.
> I think most people who have led teams will know exactly what I'm talking about.
I've had those as leads themselves, with great benefit and pain. They further convinced me about the beauty of ugly and boring.
Your line up of Lisp and Haskell next to one another is already telling - the two cultures can't be more different. Haskell culture historically have selected for people who enjoy theory for its own sake. Lisp culture genuinely prizes getting-shit-done attitude.
> What scales and works is simple and boring.
Java was exotic in 1996 and boring by 2006. If "boring" just means "widely adopted and familiar", then your notion just collapses to "what's popular is popular". True and absolutely pointless and empty.
I reckon, you're piggybacking on Dan McKinley's "Choose Boring Technology", but his point was that the innovation tokens are scarce. That is a good and true argument. But it's about organizational risk budgets, not language virtue. It says nothing about Haskell or Lisp being bad or impractical - it says being different is expensive, and you'd better be buying something with that expense. I personally disagree with that argument (in this case), because I have effectively proven that Lisp's bus factor is much smaller than even of Python or JS/TS, because modern Lisp dialects are far simpler and less convoluted and easier to train into. The experience difference and angle of opinions of two Python/JS experts can be dramatic. Having two Lispers talking "the same" language is far more plausible in practice. Not to mention that ROI from hiring a practicing Lisper (regardless of the business stack) more likely to exceed of a programmer without such knowledge.
Let me remind you that Python was considered a niche scripting toy at some point when it was the same age of [niche] Clojure today. It got boring by riding two waves that had nothing to do with the language design: web (Django/Flask) and then, decisively, being in the right place and time when scientific computing and ML needed a glue language.
Boring things survive by mass, inertia, and being unremarkable - COBOL endures because ripping it out of banks is too expensive, not because anyone loves it. Lisp survives by being remarkable - by smaller population who see the thing the majority can't, regenerating the flame across dialects out of conviction, not inertia.
What scales and works is boring, that is true. Lisp is not that, never will be, and doesn't care. What has enduring value survives regardless of adoption - that is Unix, SQL, lambda calculus itself. I'm sure you won't be arguing that any of these are impractical. Anyone can wholeheartedly accept every new rising and falling, boring COBOL and chase every new hype cycle, or just quietly keep feeding on truly everlasting ideas. Or, like in my case, nothing stands in your way of combining both - I use plenty of boring languages at work, and efficiently utilize Lisp for my personal computing. Because the darn thing just fucking works!
SICP tells me otherwise.
I'd woudn't consider SICP negative, the same with all the good CL books (Intro to Symbolic Computation, Paradigms of AI Programming...)
Both are the ur-examples on how to grasp the basic of CS well.
NuBank: from ~12M customers in 2019, grown to 25M in a year, then to 48M at IPO a year later, then to 114M in 2024, to 131M in 2025 - 991.67% growth within 6 years and still going. Not in theory, not conceptually, not because "SICP has told them". They did get-the-shit-done. Not acknowledging that Datomic and Clojure has something to do with this succes would be simply a dishonest gesture.
Walmart - the canonical "Clojure at scale" story. The eReceipts system processed every purchase across 5,000+ US stores plus online/mobile, built and maintained by just 8 developers. Architect Anthony Marcar's line after Black Friday: the system "handled its first Walmart Black Friday and came out without a scratch". They cited 5-10x less code than alternatives.
Apple - known for using Lisp for a long time.
Metabase - open-source BI. ~46k GitHub stars.
Amperity - customer data platform, "99% Clojure" - their own quote.
Netflix - been using Clojure since forever. Watch their talk from the last year's Conj. It's eye-opening on stability of complex systems.
Cisco - malware analysis platform. Multiple huge Clojure projects: IROH - Incident Response Orchestration Hub, CTIM/CTIA - Cisco Threat Intelligence Model and API, etc.
Braintree/PayPal - payments backend. CircleCI. Grammarly (this guys are on SBCL)
And that's just a short list of actual, real, profitable businesses built with and maintained using Lisp. I don't know what "SICP has told" you, but maybe you just need to look around, things have changed a bit since then.
My initial point was about cultures - Haskelites are typically very smart, extremely mathy, and they'd often choose certain ways even if it takes them forever and requires reading and analyzing dozens of academic papers, just because "Galois was a genius and we can make this theory fit here, because then we can center infinite divs on infinitely large DOM entities...", then publishes a paper "Coequalizers for Vertical Alignment: A Comonadic Approach"
A Lisper would be like: "Ahem... I wrapped the whole thing in a macro. Yes, it evals a string. Yes, the string is generated by another macro. No, I will not be explaining it. It shipped Tuesday, it prints money, it works. Gotta go, kids need dinner.."
Also, where do you go from "preferring strong CS theoretical grounds" to "cutting corners"? They don't have to be mutually exclusive.
That garbage collection that Haskell has? Guess where that came from. The whole "functions as data to pass around", guess where that came from. It was those pesky lispers on a Tuesday.
Edit: typo
Da hell you're talking about, friend? I said nothing about "people", or them being smart or dumb; just a difference in cultural stereotypes.
Now you're ironically "proving the point" I didn't make by saying some dumb shit and pulling me into this pit too. If I was actually smarter I'd probably just ignored it. Reminds me Billy Madison quote: "everyone in this room is now dumber for having listened to it. I award you no points, and may God have mercy on your soul."
Again, check HAKMEM from ITS/Maclisp/PDP10's (The OS from Richard Stallman took all the ideas for GNU Emacs, the GPL license, the free software movemement and whatnot). Lisp itself accounts for tons of papers and innovation.
On the contrary, we considered it a major reason we were able to build a quite successful stock broker and bank from scratch with a team of 4-6 people, who doubled as datacenter ops (we ran on-prem), internal tech support for the rest of the firm (~20 people) and 2.line customer support.
We quite naturally converged on a set of internal libraries for various tasks. Understanding and fixing each other’s code was not a big deal.
Coincidentally, our frontend was php. That was messier, and we conciously kept that layer as lean as possible.
Lisp dialects turned out to be extremely practical - I just can't even imagine doing the things I do today with Emacs in anything else. Achieving similar effects with any other tool would be enormously more time consuming and far more frustrating. Sure, it really took me years to get to that point, but even though I had already knew all sorts of other tools which I could've picked to achieve similar results - from bash/zsh, awk, sed and tcl to python, golang and a bunch of others, the way Lisp-driven Emacs lets me get there is beyond meaningful comparison. Nothing even comes close and I'm enormously proficient in vim, I spent almost a decade in IntelliJ and used tons of different IDEs before - from Delphi and Eclipse to Visual Studio and VSCode.
Clojure, at which I scoffed at some point, turned out to be an immensely pragmatic tool for dealing with data. Any kind of data - big or small. It effectively replaced jq in my toolbelt, all my API interrogations happen in a Clojure REPL today. Fetching data from psql, mysql, sqlite and sorting, slicing, dicing, transforming that data interactively, directly from my editor is an absolute delight.
Building simple web-scraping scripts with nbb driving Playwright is so much faster than using any other stack, even javascript is no longer "an obvious choice" for me, even though I spent decades learning its quirks.
Babashka has replaced any kind of bash-scripting - anything longer than three lines almost has no reason to be made in bash/zsh/fish anymore.
Anything Lua-driven is now done with Fennel. It's not even funny how a dozen-lines boilerplate of Lua can be compacted into a simple, reasonable three-liner Fennel macro. Or the way how I can connect to the Hammerspoon REPL and poke through visual elements of any app on Mac, interactively and with ease - is complete and total bananas.
Era of LLMs incidentally highlighted another enormous advantage of Lisp - when you give an LLM a true Lisp REPL, agents stop guessing and start empirically analyzing current state of things and produces working solution faster, costing far less tokens. And you get to watch it solve things interactively, e.g. I often let AI poke through our UI (via Playwright-driven Clojurescript REPL), while monitoring situation in k8s - through nrepl port, connected to Clojure REPL. It literally interactively walks the DOM, finds the selectors, clicks buttons, etc. All without restarts, complex state management and all.
"Well", you may say: "these examples exactly what I'd consider a 'hobby language' territory".
Alas, I have worked in teams where Clojure was used for shipping commercial software and I have seen truly complex projects - Cisco's infosec infrastructure and FindingCircle's complex Kafka topologies. I have met and talked to people working at Netflix, Apple, Amazon, Nubank, CircleCI, etc., and I can confidently say: your self-conviction is absolutely backwards.
Lisp-world has never been more cornucopian than today; we see the proliferation of different tools and new Lisp dialects popping almost every passing week - Jank, Jolt, ClojureDart, Squint, Coalton, Clojerl, LFE, uLisp, etc. It is frankly inconceivable to find today any platform where you can't really run a Lisp. My advice to any programmer who's aspired to become a hacker - do learn Lisp. It comes in handy. For real.
I don’t agree with you but your comment is very well thought out and doesn’t deserve downvotes.
Message Sent from Common Lisp
Somewhere, I have a copy of a commercial LISP for Windows which would compile to an executable --- apparently this sort of thing is still possible, but it's not widely known/used, and sadly Jean-Marie Hullot's "SOS Interface" for the Mac was co-opted to NeXTstep:
https://denninginstitute.com/itcore/userinterface/GUIHistory...
I'd dearly love to see a RAD (Rapid Application Development) tool using LISP w/ a nifty UI for working up a GUI which would compile to something easily deployed (maybe HTML5 Canvas and JavaScript) as a stand-alone/single-file web application?
re: heap based delivery: not a good idea. But, I sometimes do heap based development when I have a ton of data I want loaded every dev session, then I save a SBCL image, and restart my Lisp environment using my custom image.
AWS already has lots of AMI and docker are essentially image based.
We would version whole images in something like git, and that's all.
It’s not a hack.
inb4 DoS attack. That is a universal parsing problem and should be solved by configuring OS limits for your process.
Yes, it's nice we have control over it. This is a lisp thing, where features that are used to implement standard things (like the standard reader) are exposed so the user can play with them also.
But code written with custom read tables has some problems. Different code with different read tables may not be composable. If I have two packages that use incompatible read tables I can't import them into a third package and expect to be able to use their readtables there.
Also, it makes treating code as an object to be inspected, modified, and written out again difficult. This is similar to the problem of code rewriting systems on preprocessed languages like C or C++.
A different branch of Lisp put everything into S expressions. Interlisp, for example, had comments in the code as forms, so the code could be editted as S-expressions. But that was dropped from Common Lisp, which took the surface syntax more from Maclisp.
Quite a while back I have read about a system based on Scheme , called termite (I don't remember which scheme that was) that can actually sling live running code/closures across network and execute them remotely..
Boggles my mind even today.
“Concurrency Oriented Programming in Termite Scheme”: http://scheme2006.cs.uchicago.edu/09-germain.pdf
Implemented in Gambit Scheme: https://github.com/FredericHamel/termite-scheme
[0] https://core.tcl-lang.org/tcllib/doc/trunk/embedded/md/tclli...
We have a few services built in Clojure and we expose nrepl port on our pods in our SDEs, it's enormously helpful to test and debug things on the fly, without having to redeploy or restart anything. Without having to deal with state, caching, etc.
Also not sure what is SDE.
What stopped further development of the standard was the collapse of the market for Common Lisp.
I should note that many of the things that need changes to the language definition in other languages are just libraries in Common Lisp.
https://books.google.com/books?id=CD8EAAAAMBAJ&lpg=PA25&dq=d...
September 1991 — "Smalltalk/V code is portable between the Windows and the OS/2 versions. And the resulting application carries no runtime charges. All for just $499.95."
(Advert on the last page of "The Smalltalk Report")
https://rmod-files.lille.inria.fr/Archives/TheSmalltalkRepor...
Depends what you mean. Details matter.
> You can not build new things by using "images" as components.
Depends what you mean. Details matter.
I imagine it would look a bit like Erlang's BEAM. No need to stop and start the application, but write a script to do hot updates of a live image.
I wish more desktop applications could hit even a 100ms startup time. These days it feels like 5 seconds or more is the norm.
Web services need either cooperative concurrency or M:N concurrency due to the "10k problem". CL only supports threads (OS-level) and promises; everything else is incomplete (eg., delimited continuations, which could be used to build coroutines) due to missing parts in the spec and some language features (eg., conditions and restarts). Of course it can be done, but it won't be as pleasant as using Elixir and Phoenix.
A game engine would work, most likely, unless it was for an MMO (again, concurrency handling). I personally never worked on one, but I see examples of game engines in CL, and they tend to look nice.
In general, single-user desktop (CLI, TUI, GUI) apps are still a good fit for CL, even today (you need to put some work into packaging the app for different platforms, but it tends to be easier to set up than it is for C or C++; harder than Go or Rust, though). It's unfortunately not as good a fit for the backend, at least not until an implementation with good support for concurrency appears. It's nice as an extension language in a larger app (through ECL), and as far as dynamic languages go, it's quite performant, so some computation-heavy apps can benefit from using CL (with SBCL). On the other hand, the ecosystem is quite small, which means dependency-heavy apps are better written in something like Python or a mixture of CL and another language (there are two-way bindings to many dynamic languages and there's mature FFI support for compiled languages).
To be perfectly honest: as much as I love Lisp, I personally gave up on trying to use it, for now. For hobby stuff, I found an even more niche solution that is more enjoyable to work with in the GUI/TUI/CLI space. It also doesn't support OS-level threads, but instead provides coroutines for concurrency - I find this side of the trade-off to be useful/beneficial more often, at least in the code I tend to write. I don't believe the time spent learning CL and other Lisps was wasted, but it's become harder and harder to justify going for CL over the past 15 years, and I finally reached a point where I stopped trying. YMMV though, and I would still give CL a chance if it's your first language of this kind (i.e., providing image-based interactive development, a dynamic language with a native compiler with inline assembly support, a multimethod-based object system, and homoiconicity/macros, etc.).
What is that solution?
I don't remember the exact numbers, but when I checked, the GT+Pharo ecosystem (available packages, number of people in Discord, tools with support for the language, etc.) was ~2x smaller than Common Lisp's. It also comes with its own problems, some of which CL doesn't suffer from (the GIL, performance, startup time). But it's very fun to use and play with, which is the most important quality for me in my hobby/side-projects. :)
I'm confused by the GP's assertion that backends aren't a good fit because of the threading model, to me they're one of the best fits. The 10k problem isn't a concern for most software, and in any case there are ways around it. (I don't know what Google Flights does but even at their scale they haven't moved off SBCL. And Hacker News itself runs fine on SBCL, though there probably aren't 10k concurrent connections.) In the ecosystem, there's the https://github.com/fukamachi/woo webserver which binds to libev to handle similar scale as Go was advertising about 10 years ago. And besides some work going on recently on the SBCL dev mailing list to add native fibers/green-threads, there's been non-native versions of them before, and basically any concurrency model you can think of has been built on top of SBCL by someone. (STM, actors, async (one even built on libuv), channels, promises/futures...)
> The startup is of course nowhere near that of a small C or Zig binary, but for larger tools it will be tolerable.
It's worse than Java and Python and JavaScript I think? The languages that were always disliked for CLI/TUI/GUI apps because of unnecessary bloat they bring due to their runtimes. It's not impossible to use this ofc, it's just inferior to alternatives with minimal runtime, so such an app might be considered a temporary solution to use before someone rewrites it in Rust or Zig or C and people have no reason to use slower and more resource hoggy version. Many people even choose to avoid Emacs for slow startup times, now imagine if something like grep was starting a virtual Lisp Machine underneath. This is why I think it's more promising to consider it for apps and niches that people never tried to keep minimal, such as games and webservices, even if it doesn't have native coroutines or whatever. Using non-standard solution is almost a non-issue and invisible to end user while startup times and RAM usage are very visible.
Also, ofc there's definitely unique things that become available with something that's just as programmable in runtime as it is in development stage. So some kind of very polymorphic app that benefits from growing more native code in response to user actions, could benefit from it. I don't have many ideas of what app really needs this though.
In the past, like two decades ago, I've seen a person using SBCL with some kind of unofficial continuations or green threads for backend webdev in commercial setting. I also remember someone using it in context of virtualization systems, but don't remember their exact usecase.
Also quick search shows there are some modern takes on coroutines as well: https://atgreen.github.io/repl-yell/posts/sbcl-fibers/
Not mine, but interesting.
I wanted something more 'algorithmic' - and more accurate.
So me and Claude build an sbcl-based Film Recommendation system. Type in a new film name, it goes to open film database OMDB, grabs the scores, and then, using films I have already rated and with a built-in tiny Neural Net, gives me a personal recommendation. It uses the OMDB data and an algo that weights those with my personal values (in half a dozen areas: overall, acting, cinematography, etc), along with a 'comments' box to note for friends / others.
The code is very well-done CL, heavily commented. The film & ratings database is stored as S-exprs, naturally, all in one file. I don't use a database as I only have a few hundred films, but maybe later I will. And that's the point -- this is a living chunk of code that I from time to time bolt in new features, or try new things (e.g. the UI is localhost:8080)
I fretted about having a 'real' project to really dig into CL for a long time, and finally, found a meaty-enough project that ends up being really useful & quite a learning (continuing learning) experience. I start it up inside emacs/sly like this:
(ql:quickload '(:hunchentoot :dexador :yason))
(load "s:/filmrec.lisp")
(filmrec:start)
I have to set the omdb key: (setf filmrec:*omdb-api-key* "fxxxx70")
Then, every so often, I retrain the NN: (filmrec:retrain)
Good Luck, you'll find a project. And with an LLM buddy, you'll succeed.CCL isn't very actively maintained and currently doesn't have an ARM64 port, but otherwise continues to work fine. I believe one reason people use it is that it compiles a bit faster than SBCL, at least in part by doing less optimization.
I’d recommend using close parens for your code sample. Those are portable between the two.
(funcall (funcall (funcall (funcall ; ...
...though I don't think that functions which return functions which return functions which return functions ad infinitum are a great idea. Simply taking a value and returning a value means you can use a pipelining operator: (~> some-data
function-1
function-2
(function-3 _ some-other-data)
; ...
function-n)