Cakelisp: A performance-oriented Lisp-like language
macoy.me
macoy.me
> Note that while Cakelisp has "Lisp" in the name, Cakelisp takes some inspiration from Lisp, but is not compatible and does not aspire to become "a Lisp". I was inspired by Naughty Dog's use of GOAL, GOOL, and Racket/Scheme (on their modern titles). I've also taken several ideas from Jonathan Blow's talks on Jai.
> I also think garbage collectors add more complexity than manual management
That's quite the controversial statement and flies in the face of what GC has enabled in software development generally over the last few decades.
I would be excited to understand some examples where this is the case and they outweigh the benefits that GC brings to developing software (incl. games).
In the author's list of similar languages (https://macoy.me/code/macoy/cakelisp/src/branch/master/doc/V...) they mention two other lisp-like languages without GC: Liz (transpiles to Zig) and GameLisp (seamless Rust API).
Even Unity which uses garbage collected C# for game code is still a C++ engine under the hood for much of the performance critical engine code.
Having worked in games and VR development for many years I can say that memory management was not a major problem in C++ and for tricky areas of memory and resource management like GPU memory garbage collection doesn't generally help you.
When it comes time to optimize memory usage and performance it's often easier when memory management is explicit, deterministic and visible as well as highly customizable than when you have to work with a garbage collector which is a bit of a black box and has a lot of non deterministic and unpredictable behaviour.
Even after working for several years primarily in Unity with C# I still tend to prefer non garbage collected languages for games.
int in C can be anything with at least 16 bits.
This seems potentially confusing, since usually "int" just refers to a signed integer of some platform specific size.
Maybe it would be better to say something like, "int is like uint32_t, 32 bits and no sign bit without any additional data"?
Viewed as a replacement for the C preprocessor, or perhaps for C++ templates, this is very compelling. When you know the C you'd like to write, but it's annoyingly verbose and updating it by hand means changing a dozen places at once, systems like this amount to a more structured code generator.
It might be worth copying the sometimes-garbage-collected approach. In particular, you could have real garbage collection at compile time and raise an error if any of the residual code wants to call into it.
[0] https://github.com/raysan5/raylib/blob/master/BINDINGS.md
Cakelisp: A Programming Language for Games - https://news.ycombinator.com/item?id=25491568 - Dec 2020 (64 comments)
I'm not just saying this to be pedantic. It's important to note that every GC method involves some overhead and has a potential to make execution time less deterministic. This is certainly true of reference counting, generally true of object pooling, etc. There are even cases where tracing GC improves locality of reference vs. other methods, and thus improves performance and predictability, though those are rare AFAIK. So when you say "extract every last CPU cycle" it's important that such a goal does not necessarily favor some other approach.
Many would also say that an aversion to tracing GC does not justify having nothing beyond plain malloc/free. No borrow checker, no reference counting (which can be done with very low overhead), no arena or custom-allocator support? Not in 2023. Leaving programmers entirely on their own for memory correctness is an eminently questionable choice, especially when other language features make gratuitous or hidden allocations easy. As a C programmer for 30 years I'm not going to say it's an illegal choice, but it certainly needs more than "but games" to justify it.
The really cool thing is that supporting custom allocators in a language and its libraries (e.g. Zig) makes both approaches easier, with less boilerplate. I see what's going on with the borrow checker in Rust and - as a long-time fan of static analysis - I understand that it might theoretically be better, but I find it hard to get very excited when I see that the implementation difficulty and cognitive load are so much higher than a simpler approach I've already seen work well.
nobody ever told me, check it out, it's not hard to make like the dumbest possible "bump allocator", where you allocate a hunk of memory and dole it out bit by bit as the application requests it, and then later you can just free the whole hunk at once… or even just move the bump pointer back to the start, and reuse it next frame/request/etc.! that's like 95+% of the reason why people reach for things like garbage collection to begin with, and it seems so obvious in hindsight!
actually, it was this top-shelf HN comment that really spelled it all out for me, and again, it all seems so obvious in hindsight: https://news.ycombinator.com/item?id=26443768&p=2#26451692
If you mean popular as in the antonym of unpopular I don't think elisp can be called popular. I have written several thousand lines of elisp outside of my Emacs config, and it is probably my least favourite lisp - and I believe most people who know more lisps than elisp think like I do.
Dylan was a great language - I played with OpenDylan a bit. Scheme with CLOS and gradual typing, and a formal specification, and a stdlib, and tools for modularizing and AOT compiling and linking multi-module projects, hygienic (syntax-case-style) macros, and so on, all in ca. '95! It was a bit too late and Java took over the world before Dylan had its chance... Imagine the world, full of sunshine and rainbows, if Dylan prevailed - instead of the dreary, stifling, primitive language we all know and love (to hate).
Racket is doing nothing similar to Dylan. Dylan was a well defined language for programming in the large and targeted at enterprises. Racket is a laboratory and a workbench for creating languages. It accomplishes this by implementing incredibly powerful macro and module systems. Other notable features of Racket are delimited continuations, contracts, and the Typed Racket dialect. It is targeted at researchers and beginners and has nothing to do with the enterprise. :)
I'm a Common Lisp fan, but nobody would claim that it is popular. I don't know that "popularity" is as subjective as you describe.
It's completely subjective. The objective metrics (if web search are them, which is kind of dubious) tell us that whatever-language-you-like is probably orders of magnitude less popular than Fortran. The "real" popularity that you experience - how big the community is, how many packages are published, how many success stories are there - heavily depend on where you are, who you know, and what you want.
The index: https://www.tiobe.com/tiobe-index/