As such you get all the nice stuff that has made Lisp a great language, plus access to modern libraries.
Note that since Common Lisp there has not been another standard, and in what concerns Scheme, Dr Raket is more relevant. Also R7rs Large has been hanging on for years now.
Scheme gets close but has some odd naming conventions and completely wild conventions for packages (SFRI, etc). CL's entire library is full of incredibly odd names first established at the very advent of computing. Using it can be...dense. And inconsistent, since it's not purely functional and has no dedicated data structure syntax.
Anyway my recent favorite is Carp:
https://github.com/carp-lang/Carp
Serious projects in it? Zero
Also, living on a host language has always been part of its ethos. So if you want to be Lisp on C++ or Lisp on Rust, you’re going to be more ideologically aligned with the Clojure crowd than the Common Lisp crowd who pinch their nose and say ALGOL when you mention either.
http://www.lichteblau.com/sbcl/doc/manual/sbcl/Foreign-Funct...
Maybe it’s too much work to write a full lisp vm in another language when it’s easier to write a loader.
> Be kind. Don't be snarky. Converse curiously; don't cross-examine. Edit out swipes.
We try to avoid condescending put downs here.
With regards to walmarts adventures in clojure:
https://news.ycombinator.com/item?id=19728502
TIL Walmart Labs was so into clojure. I would really like to know to what degree they still are — does datomic have Walmart as a customer?
I'm guessing that's why we nowadays have Facebook-like comments responding to a title with "I don't actually have any experience with the subject, and never heard about that, wow!" and similar.
Every single Clojure submission inevitably have someone mention Walmart. Cool, but do we need to add that to every submission, unless there is something new about it, or something we could actually discuss? And even more important, could those things be said by the people who actually have knowledge about it?
I'm not in C# submissions sharing what I know or don't know about C#, because I'm not in the ecosystem, and it doesn't make sense to write comments about stuff even I know I don't know about, unless I'm asking about something or similar. Like what's the point even?
Except maybe the compilation to native binary, this is closer to clojurescript than clojure I suppose ?
How about a comparison with Jank?
I'm already a big fan of the scheme-rs crate.
I use it any time I need a dynamic scripting language.
It allows for more flexible hot-reloading of parts of a program.
I don't personally have any Clojure interop holes that need filling.
But I can imagine a future where one moves partially away from the JVM if e.g. faster starts or leaner container images are desired.
My guess is, within the next 3-5 years, most ALGOL descendant languages will become obsolete, and S-exp based Lisp dialects will take over. Objectively superior.
Behold a native kernel, no inline asm or linker scripts, of any kind. The full compiler pipeline is controllable through the compiler (you can arbitrarily target, devise, or enable/disable various optimization passes, for instance you can enable LICM at will). Also has a hard 1:1 correspondence to C/C++/Rust/adding more languages soon.
;; GNU multiboot kernel
(image (target x86-64) (origin 0x100000) (entry "boot32")
(section ".multiboot" (align 4) (keep))
(section ".bss" (align 4096) (zero))
(stack "bootstrap" 16384) (stack "kernel" 32768)
(assert (<= (address "kernel.end") 0x40000000) "early memory must fit the first GiB identity map"))
(static header (Array u32 8)
(declare (section ".multiboot") (used) (link-name "multiboot_header"))
(arr (0x1badb002 0x10003 0xe4514ffb
(link u32 (address "multiboot_header")) (link u32 (origin))
(link u32 (+ (origin) (image-size))) (link u32 (+ (origin) (image-size)))
(link u32 (address "boot32")))))
(static gdt (Array u64 3) (declare (aligned 8) (link-name "boot_gdt"))
(arr (0 0x00af9a000000ffff 0x00cf92000000ffff)))
(static pml4 (Array u64 512) (declare (mutable) (aligned 4096) (link-name "boot_pml4")))
(static pdpt (Array u64 512) (declare (mutable) (aligned 4096) (link-name "boot_pdpt")))
(static pages (Array u64 512) (declare (mutable) (aligned 4096) (link-name "boot_pages")))
(fn prepare-paging ()
(declare (mode protected32) (noinline))
(dotimes (i 512)
(at pml4 i (->u64 0)) (at pdpt i (->u64 0))
(at pages i (| (* (->u64 i) 0x200000) 0x83)))
(at pml4 0 (| (link u64 (address "boot_pdpt")) 3))
(at pdpt 0 (| (link u64 (address "boot_pages")) 3))
(unsafe
(x86::write-cr 'cr3 (link u64 (address "boot_pml4")))
(x86::write-cr 'cr4 (| (x86::read-cr 'cr4) 32))
(x86::write-msr 0xc0000080 (| (x86::read-msr 0xc0000080) 256))
(x86::load-gdt (link VirtAddr (address "boot_gdt")) 23)))
(fn show-greeting ()
(unsafe
(auto video (i->ptr (Volatile u16) 0xb8000))
(dotimes (i 2000) (at* video i (+ 0x5725 (->u16 i))))
(auto greeting ":d")
(dotimes (i (size greeting))
(auto byte (->u8 (at greeting i)))
(at* video i (| 0x0f00 (->u16 byte)))
(x86::out8 0xe9 byte))
(x86::out8 0xe9 10)))
(boot-entry boot32 (mode protected32)
(handoff (magic eax u32) (information ebx PhysAddr))
(with-stack "bootstrap"
(prepare-paging)
(unsafe
(x86::enter-long-mode 'kernel64 8 magic information (link u64 0x123456789abcdef0)))))
(boot-entry kernel64 (mode long64)
(handoff (magic rdi u32) (information rsi PhysAddr) (cookie r12 u64))
(with-stack "kernel"
(unsafe
(x86::write-segment 'ds 16) (x86::write-segment 'es 16) (x86::write-segment 'ss 16)
(auto valid (and (= magic (->u32 0x2badb002)) (> (address-bits information) 0)
(= cookie (->u64 0x123456789abcdef0))
(= (& (x86::read-cr 'cr0) 0x80000001) 0x80000001)
(= (& (x86::read-msr 0xc0000080) 0x500) 0x500)))
(if valid (show-greeting)
(progn (x86::out8 0xe9 70) (x86::out8 0xe9 10))))))In AI-driven world, programming languages have become more of a hobby, especially in regards to syntax/semantics. Importance is now mostly solely on tooling quality features and compiler-enforced guarantees. Rust has always been popular "written in" target, even more now, and probably the last language shift for a long time, offering compiler-time memory safety, excellent compile messages, packaging/deployment ergonomics, etc.
My guess is, your language (as is the submitted one) compiler/tooling is written in Rust and made by/in-assistance-with AI, probably Claude.
From a quick glance over your example, it looks like a hodgepodge of Scheme, Clojure, and Common Lisp with some Rust-y constructs in it. If you don't mind elaborating, why not take some existing "embedded" dialect like Pre-Scheme and compile that? Because currently this looks a lot more like Rust-with-parenthesis rather than a Lisp. Of course if that's the goal then that's fine, but I'd like to hear some elaboration on that.
It seems like the idea of the macro, and more generally of expressing code succinctly, is the closest to obsolete in my memory?
The other half of the Lisp sales pitch (image based development, constantly inspect state, hot swap code, REPL, etc) seems like what has retained currency in the LLM age.
The compiler becomes a library in the host language. As you can use the syntax of the host language for the compiled language, you can create host-side defining forms like (define-compiled-function [NAME PARAMS & BODY]) which parse the body of the compiled function into an AST and bind the resulting data structure into a namespaced variable of the host language. This way you can rely on the host's namespacing mechanisms and probably reuse even its packaging and code distribution model for your low level language.
Another interesting feature which just "falls out" is compiler macros: you can use ordinary functions of the host language as macros (code transformers) in the compiled language.
Then you can write a lowering function which takes one of these AST vars, walks its call graph, resolves references and lowers the whole thing into your target language, be it Python, Go, LLVM IR, assembly, whatever.
If you pass a context to your lowering function which binds settings dynamically like target arch, word size, C calling convention, etc. then the code generators can emit the corresponding lowerings and you get portability using the dispatch/polymorphism facilities of the host language.
This way you can push most of the complexity of the language to the LISP side. Basically you get a programmable compiler for your low level language.
I expect to see a lot more examples of this pattern in the coming years.
That seems true in a world where we completely stop looking at code. Right now my reality is giant verbose PRs written by agents in Java, and it sucks to review.
So I guess the idea is tastemaker humans spend all their time coming up with sweet macros and telling agents to refactor the ever shrinking code base.
But even still I think the main argument for S-Expressions (it’s easiest for humans to create DSLs by working on serialized AST) has become weaker. If DSLs are the best way to make a code base readable, you can now have your agent create one with whatever syntax you like!
I think these things are going to be true:
- For a specific well-defined coding task, an LLM coding agent will be able to execute it quicker than humans, regardless of how it does it.
- Codebases which are well organised will be easier for an LLM to manipulate than codebases which are obscure and surprising.
I mean.. I think it's plausible that something like "lisp makes DSLs easy, DSLs are a great way to arrange code" is especially true with LLMs; but I'd also think you'd need to know when to use (& when to not use) DSLs to get effective results from this.
Whereas, say, you could have the LLM come up with a DSL in a way which is high friction for the LLM to do it ... but, you'd get the result a bit slower, & maybe worse.
I’ve been experimenting with stuff like “this project is a Kahn process network, every change is strict conformer to that model, add features only by adding nodes”. As a bonus if you’re strict then porting the specific implementation to a new language should be easy.
To me stuff like this feels like the future of programming.. details don’t matter but design language does. not leet code of fancy data structures from scratch but at least a basic familiarity with LOTS of them, a working knowledge of vast zoos of expressive patterns and automata, etc.
Seems more important than ever? Every model degrades the more context you use, programs that can be described more succinctly will be better made, at least when using LLMs to create these, as it's much easier to fit more "meat" per token.
I'm on the same "S-Expressions taking over is inevitable" but to be fair, I've been on this train for the last decade so maybe I'm slightly biased.
I don’t really have faith that I could write macros of such incredible brilliance that it would outweigh the models’ facility with Python.
(Integer/parseInt my-variable); this calls Integer.parseInt(my_variable) in Java-land
I tried to find examples for how to call Rust code and the best I could find is:
https://github.com/csm/clojurust/blob/b847a29b46e2b6b3fbe624...
It looks like you need to do a lot of leg work to introduce Rust functions into Clojure namespaces. I guess there is no way around it and this is not a criticism of clj.rs. But it doesn't seem to be as seamless as on the JVM.