Clj.rs – a Clojure dialect implemented in Rust

105 points - last Wednesday at 3:23 PM

Source

Comments

vaylian today at 1:11 PM
One of the killer features of Clojure is it's seamless interop with the host platform. On the JVM you do something like

(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.

JavierFlores09 today at 11:19 AM
Has Clojure become the new base for Lisp-like languages? What does it got going for it that people seem to want its specific flavor of lisp? Just asking since I've also seen the Clojure talk about Jank[1] recently and it has gotten me interested.

1: https://www.youtube.com/watch?v=tHgApFhevrQ

tux today at 9:41 AM
Why not name it “Cloju.rs” instead? :-)
xnfra today at 12:41 PM
The only thing I know about Clojure is Walmart used it to rewrite their entire inventory system.
jiehong today at 9:07 AM
Nice, but what are the non goals?

Except maybe the compilation to native binary, this is closer to clojurescript than clojure I suppose ?

How about a comparison with Jank?

arikrahman today at 1:49 PM
Love to see more Clojure dialects taking fruit. Jank is very promising for C++ and now we have the Rust complement
andersmurphy today at 12:32 PM
Claude sure is busy these days.
mono442 today at 12:54 PM
It's vibecoded which makes it unlikely it has been actually tested well.
sshine today at 9:25 AM
Cool.

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.

rfgplk today at 10:42 AM
I'm working on something similar.

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))))))
lightningspirit today at 10:45 AM
I expect this to take over within the next couple of years. Great job!