Skip to content(if available)orjump to list(if available)

Roc rewrites the compiler in Zig

Roc rewrites the compiler in Zig

52 comments

·February 4, 2025

zoogeny

It's nice to see Zig continuing to gain support. I have no idea why I've ended up siding with Zig in the lower languages wars.

I used to root for the D programming language but it seems to have got stuck and never gained a good ecosystem. I've disliked Rust from the first time I saw it and have never warmed up to it's particular trade offs. C feels unergonomic these days and C++ is overfull with complexity. Zig feels like a nice pragmatic middle ground.

I actually think Rust is probably perfectly suited to a number of tasks, but I feel I would default to choosing Zig unless I was certain beyond doubt that I needed specific Rust safety features.

bornfreddy

I wanted to like Rust (memory safety and performance - what's not to like?) but both of my experiments with it ended in frustration. It seemed a way too complex language for what I needed.

Recently, a coworker of mine made a great observation that made everything clear to me. I was looking for a replacement for C, but Rust is actually a replacement for C++. Totally different beast - powerful but complex. I need to see if Zig is any closer to C in spirit.

pcwalton

> I was looking for a replacement for C, but Rust is actually a replacement for C++. Totally different beast - powerful but complex.

I've seen this sentiment a lot, and I have to say it's always puzzled me. The difference between Rust and basically any other popular language is that the former has memory safety without GC†. The difference between C++ and C is that the former is a large multi-paradigm language, while the latter is a minimalist language. These are completely different axes.

There is no corresponding popular replacement for C that's more minimalist than Rust and memory safe.

† Reference counting is a form of garbage collection.

fc417fc802

Somewhat related, even when I work with C++ I use it as "C with RAII". What I actually want is a scheme (R5RS) with manual memory management and a borrow checker. I don't know how well such a monstrosity would actually work in practice, but it's what I've convinced myself that I want.

huijzer

I read a blog that called Rust a language that was aimed to be high-level but without GC.

smartmic

From what you describe, you might also like Odin.

greener_grass

I can't help but feel like the Roc team has an attitude of "imperative programming for me, but not for thee".

And now they are doubling down on that by moving from "OCaml meets C++" to "C, the good parts"!

If FP isn't good for writing a compiler, what is it good for?

btreecat

> If FP isn't good for writing a compiler, what is it good for?

Summing the Fibonacci sequence I guess.

agumonkey

other FP languages bootstrapped onto themselves IIRC

whlr

According to [1], they want to use a systems-level language for performance.

[1] https://www.roc-lang.org/faq#self-hosted-compiler

tialaramex

"The split of Rust for the compiler and Zig for the standard library has worked well so far, and there are no plans to change it."

I assume that statement will need updating.

munchler

As an FP fan, I agree. This is disappointing.

kristoff_it

Huh? The whole point of Roc is to let you easily put both imperative and functional code in the same project through Roc's platform system.

You get to decide what part of your code should be imperative, and which should be functional.

greener_grass

So why is it a non-goal of Roc to be implemented with this approach?

IshKebab

This is the first justification of not using Rust that I actually agree with. Well written.

I recommend reading Roc's FAQ too - it's got some really great points. E.g. I'm internally screaming YESSS! to this: https://www.roc-lang.org/faq.html#curried-functions

But then it has other weird features too, like they seem to be really emphasising "friendliness" (great!) but then it has weird syntax like `\` for anonymous functions (I dunno where that dumb syntax came from by Nix also uses it and it's pretty awful). Omitting brackets and commas for function calls is also a bad decision if you care about friendliness. I have yet to find a language where that doesn't make the code harder to read and understand.

mrkeen

It's the closest you get to 'λ' on a US keyboard.

Skinney

The syntax came from Elm, which got it’s syntax from Haskell (where Nix also got it from) which got its syntax from ML.

It’s a syntax that’s several decades old at this point.

It’s different, but not harder. If you learned ML first, you’d found Algol/C-like syntax equally strange.

wk_end

(ETA: speaking strictly about anonymous functions; on rereading you might be talking about the absence of parens and commas for function application.)

That's not ML syntax. Haskell got it from Miranda, I guess?

In SML you use the `fn` keyword to create an anonymous function; in Ocaml, it's `fun` instead.

throwaway17_17

I believe the `\` character for functions is original to Haskell. Miranda does not have anonymous functions as a part of the language.

hillcapital

They recently changed the syntax to add parens, commas and use `|arg|` for closures :)

https://github.com/roc-lang/roc/releases/tag/0.0.0-alpha2-ro...

xiaodai

R has that too.

wiz21c

I use rust a lot but, Roc is right: compilation times are not proportional to the safety you gain. At least in my project.

flooow

From listening to Feldman's podcast, this doesn't really come as a surprise to me. The rigor that Rust demands seems not to jibe with his 'worse is better' approach. That coupled with the fact they already switched the stdlib from Rust to Zig. The real question I have is why he chose Rust in the first place.

gregwebs

Go was built while waiting for C++ to compile- fast compilation was an implicit design goal.

Rust on the other hand didn’t prioritize compile times and ended up making design decisions that make faster compilation difficult to achieve. To me it’s the biggest pain point with Rust for a large code base and that seems to be the sentiment here as well.

pcwalton

Rust always cared about compile times. Much of the motivation to switch from rustboot to rustc was compile times.

(Source: I wrote much of the Rust compiler.)

null

[deleted]

debugnik

> we also want to convert [the parser] to use recursive descent; it was originally written using parser combinators

Almost all parser combinators are recursive descent with backtracking, they just add higher-order plumbing.

I have a feeling that whatever issue they've encountered with the combinator approach could have been worked around by handwriting only a few pieces.

wirrbel

When I used parser combinations in rust years ago the compile times were really long. In also think it’s a strange reason to move away from rust as a language.

bmacho

Strangely they don't mention that (allegedly? According to them at least) they already use Zig for the standard library[0]. Which was also started to be written in Rust, then it got rewritten in Zig:

[0] : https://www.roc-lang.org/faq#rust-and-zig

laserbeam

> (and to unblock updating to the latest Zig version, which we've use for our stdlib for years)

It's somewhere in the middle of the list of the "Why now?" section.

thegeekpirate

They do mention it but there's only 10k lines of Zig, so it's hardly a blip in the grand scheme of things.

chambers

This decisions looks well-reasoned. It acknowledges the strengths of their current implementation, and explains why another language may serve their goals even better. I can follow along as someone interested in general software decision-making, even though I'm not particularly invested in either language.

One specific thing I like is that the motivation for this rewrite is organic, i.e., not driven by an external pressure campaign. It's refreshing to see a drama-free rewrite.

Lyngbakr

The rationale given makes perfect sense, but isn't it risky to rewrite in a language that is yet to hit 1.0?

UncleOxidant

What is Roc? Here it is: https://www.roc-lang.org/

greener_grass

> While we're at it, we also want to convert it to use recursive descent; it was originally written using parser combinators because that was what I was comfortable with at the time

Aren't parser combinators just one way to do recursive descent?

jjk7

Explicitly hand-writing the parsing logic allows you to get more specific in error states and messages that a combinator can't.