[HN Gopher] Roc rewrites the compiler in Zig
       ___________________________________________________________________
        
       Roc rewrites the compiler in Zig
        
       Author : todsacerdoti
       Score  : 333 points
       Date   : 2025-02-04 17:21 UTC (1 days ago)
        
 (HTM) web link (gist.github.com)
 (TXT) w3m dump (gist.github.com)
        
       | cma256 wrote:
       | It will be interesting to compare compile times afterwards. I'm
       | also interested if there's any Rust features that are 'taken for
       | granted' which will make the Zig version less pleasant to read or
       | write. Hopefully the old Rust repo is archived so I can reference
       | it a year from now!
        
         | badfishblues wrote:
         | It will be impossible to ever truly do a one-to-one comparison.
         | First, there may be a ton of code in the existing
         | implementation that gets cut out by a mass rewrite due to
         | better, more informed, architecture decisions. On the other
         | hand, it may be possible that new features find their way into
         | the rewrite that cause the fully Zig implementation to be
         | larger than the original Rust-Zig implementation. I don't think
         | any comparison will be fully "fair". A smaller implementation
         | could be argued as only being possible in Rust or Zig because
         | of its advantages over the other language. I expect results to
         | be controversial.
        
           | bhansconnect wrote:
           | Yeah, the rewrite will clean up a ton of technical debt for
           | us. So it will very much be a bad comparison.
        
           | gauge_field wrote:
           | I am also curios about at least some benchmark even if it is
           | not one-to-one perfect comparison. There should be at least
           | one case-study where they have shorter feedback loop with Zig
           | than with Rust. It would be interesting to see that.
        
       | hassleblad23 wrote:
       | Zig seems to be a good choice here.
        
         | UncleOxidant wrote:
         | > Rust's compile times are slow. Zig's compile times are fast.
         | This is not the only reason, but it's a big reason.
         | 
         | So why not something like OCaml that has fast compile times and
         | a lot of nice features for writing compilers? (pattern
         | matching, etc.)
        
           | whytevuhuni wrote:
           | Because, like he said, compile times matter.
           | 
           | This includes the Roc compiler too. Zig is significantly
           | faster than OCaml.
        
             | LAC-Tech wrote:
             | The Ocaml compiler is significantly faster than the Zig
             | one. It's one of the fastest I've seen.
        
               | whytevuhuni wrote:
               | Ah, sorry, I was referring to the speed of the resulting
               | Roc compiler.
               | 
               | A Roc compiler written in Zig would compile Roc code
               | significantly faster than a Roc compiler written in
               | OCaml.
        
               | LAC-Tech wrote:
               | Ah! That makes sense.
        
           | platinumrad wrote:
           | The same reason why they're not self-hosting. They want
           | compiler performance to be in the top C, C++, Rust, Zig tier.
           | OCaml isn't slow, but at best it's in the second Java, C#,
           | etc. tier.
        
           | henning wrote:
           | Zig's union enums get you something kind of like pattern
           | matching. https://zig.guide/language-basics/unions/
        
           | theLiminator wrote:
           | I guess if you want to never limit yourself in terms of
           | performance, you're kinda stuck with either
           | C/C++/Zig/Rust/etc.
           | 
           | GCed languages can be fast, probably even as fast as any of
           | the aforementioned languages with enough engineering effort,
           | but in terms of high performance, it's actually easier to
           | write high performance code in the aforementioned languages
           | rather than in a GCed language.
        
             | pjmlp wrote:
             | OCaml is fast enough for writing hypervisors, unikernels,
             | networking drivers, powering all Jane Street's business.
        
       | UncleOxidant wrote:
       | What is Roc? Here it is: https://www.roc-lang.org/
        
       | pjmlp wrote:
       | The way compile times are stressed all over the place is a very
       | good point.
       | 
       | Papercuts like this do make or break adoption.
       | 
       | Even C++ is improving on that front.
        
         | nurettin wrote:
         | ccache made C++ usable for me.
        
           | Cyph0n wrote:
           | https://github.com/mozilla/sccache
        
           | pjmlp wrote:
           | It has been mostly usable to me with binary libraries,
           | precompiled headers, incremental compiling and linking, and
           | now modules.
           | 
           | Although ClearMake object sharing was quite neat experience
           | back in the day.
        
         | pcwalton wrote:
         | As is Rust. And the C++ compiler performance improvements in
         | LLVM apply to Rust.
        
           | pjmlp wrote:
           | I was talking about C++ 20 modules and C++23 modularised
           | standard library, and that has little to do with LLVM, rather
           | clang.
           | 
           | LLVM improvements will do little to improve Rust, because the
           | major issue is the lack of parallelism and massive amount of
           | LLVM IR that the fronted gives to the backend to handle.
        
             | pcwalton wrote:
             | > LLVM improvements will do little to improve Rust
             | 
             | Falsified many times during Rust's development.
        
               | pjmlp wrote:
               | Not to the extent C++ modules have improved compile
               | times, as already visible in VC++ and clang/cmake/ninja
               | latest.
               | 
               | Yes, Rust compile times have improved a lot, still I get
               | better ones in C++, without having to reach out external
               | tools.
               | 
               | Bevy's tutorial for compile times shouldn't be needed in
               | first place.
        
       | rubenvanwyk wrote:
       | After watching YT talks on Roc using Rust and Zig, I always
       | wondered they didn't just opt for Zig only. Interesting to see
       | this.
        
         | bhansconnect wrote:
         | Yeah, the compiler was started in 2019 when zig wasn't nearly
         | as viable of an option. On top of that, you don't necessarily
         | know what you want until you build something.
         | 
         | I'm part of the core team, and I'm honestly still a bit
         | surprised we're switching to zig. I think it makes sense, it
         | just kinda finally aligned and was decided now. I guess enough
         | technical debt piled up and the core of the language was
         | clearly discovered. So we really know what we want now.
        
       | bmacho wrote:
       | 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 wrote:
         | > (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 wrote:
         | They do mention it but there's only 10k lines of Zig, so it's
         | hardly a blip in the grand scheme of things.
        
       | baq wrote:
       | A very good discussion and hard to disagree with conclusions.
       | Also, educational.
        
         | cardanome wrote:
         | Richard Feldman is an amazing educator. He got me into Elm back
         | in the days.
         | 
         | I am a bit sad that Roc is following similar pitfalls as Elm in
         | its quest to be simple by rejecting to have more advanced type
         | system features. That just does not work. In dynamic languages
         | you can opt for minimalism because everything goes by default
         | but in fully statically typed languages things can painful
         | quickly. Even golang had to add generics.
         | 
         | Still many amazing ideas in the language. The platform concept
         | is pretty neat. Not doing implicit currying is a good move.
        
           | Hasnep wrote:
           | But Roc already has generics, Go has managed to become very
           | successful despite having a simpler type system than Roc.
        
           | bbkane wrote:
           | What particular type system featured do you miss? I think Elm
           | proved that a restricted type system DOES WORK for large
           | amounts of software. It's been a few years since I've written
           | Elm, so I don't recall specific painful memories I've had
           | with the type system.
           | 
           | One thing that makes Go's restrictive type system more
           | bearable is a fantastic stlib package for analyzing and
           | generating Go code. I wonder if Roc will get anything
           | similar.
        
           | forgotmypass1 wrote:
           | What kind of advanced type system features?
        
           | 1-more wrote:
           | If you're talking about typeclasses, Roc calls them
           | "abilities" https://www.roc-lang.org/abilities
        
       | greener_grass wrote:
       | > 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 wrote:
         | Explicitly hand-writing the parsing logic allows you to get
         | more specific in error states and messages that a combinator
         | can't.
        
       | Lyngbakr wrote:
       | The rationale given makes perfect sense, but isn't it risky to
       | rewrite in a language that is yet to hit 1.0?
        
         | stevage wrote:
         | Much better before than after!
        
           | Lyngbakr wrote:
           | Why? There's the possibility that Zig will introduce breaking
           | changes and the Roc compiler will have to be revised in light
           | of those changes.
        
             | brokencode wrote:
             | I'm assuming the previous commenter thought you were
             | referring to Roc being pre v1 and not Zig.
             | 
             | There are probably some risks to it. And I think that you
             | wouldn't want to release a Roc v1 before Zig v1 as well.
             | 
             | But if things are working well now, you could always stay
             | on an older version of Zig while you rewrite things for
             | breaking changes in a newer version.
             | 
             | Still potentially a pain, but Rust is post v1 and they
             | ended up deciding to rewrite anyway, so there are no
             | guarantees in any approach.
        
         | bhansconnect wrote:
         | For sure, but we have a really good relationship with the zig
         | folks and they are willing to help us out.
         | 
         | On top of that, zig has gotten a lot more robust and stable of
         | the last few releases. Upgrading is getting smoother.
         | 
         | But yeah, it is a risk.
        
       | IshKebab wrote:
       | 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.
        
         | Skinney wrote:
         | 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 wrote:
           | (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 wrote:
             | I believe the `\\` character for functions is original to
             | Haskell. Miranda does not have anonymous functions as a
             | part of the language.
        
               | pezezin wrote:
               | The \ is a simplified lambda, because most programmers
               | can't type l easily.
        
             | needlesslygrim wrote:
             | Well, ML (or at least the first versions of it) used a lx *
             | x syntax [1] for l-abstractions, the same (excluding the
             | use of * over .) notation as used with the Lambda Calculus,
             | and I've always assumed \ was an ASCII stand in.
             | 
             | [1]: https://homepages.inf.ed.ac.uk/wadler/papers/papers-
             | we-love/... (can be spotted on page 353)
        
               | wk_end wrote:
               | That paper isn't showing real ML syntax itself; it's a
               | mathematical presentation to demonstrate how the type
               | system algorithm works. The actual original LCF/ML syntax
               | would differ. I don't believe it used an actual lambda
               | character, although for the life of me I can't find any
               | evidence one way or another, not even in the LCF source
               | code (https://github.com/theoremprover-museum/LCF77)
               | 
               | But yes, the slash is just an ASCII stand-in for a
               | lambda.
               | 
               | ETA: I tracked down a copy of the Edinburgh LCF text and
               | I have to eat crow. It doesn't use a lambda, but it
               | _does_ use a slash rather than a reserved word. The
               | syntax, per page 22, is in fact, `\x. e`. Similar to
               | Haskell 's, but with a dot instead of an arrow.
               | 
               | https://archive.org/details/edinburghlcfmech0000gord
        
               | needlesslygrim wrote:
               | Well if you're going to eat crow, I may as well eat
               | pigeon, for I didn't realise that paper wasn't showing
               | real source.
               | 
               | Thanks for the link to the LCF text though :^)
        
         | xiaodai wrote:
         | R has that too.
        
           | Iwan-Zotow wrote:
           | really? thought it just function(x)
        
         | mrkeen wrote:
         | It's the closest you get to 'l' on a US keyboard.
        
           | LAC-Tech wrote:
           | I believe Haskell uses it as well.
        
           | nemo1618 wrote:
           | my hot take: the language should accept \, but formatters
           | should replace it with l
        
             | IshKebab wrote:
             | Lean does symbols very well. You can just type \r and it
             | will replace it with a right arrow as you type.
        
           | fuzztester wrote:
           | IIRC, Richard explain that in one of his videos about Roc. I
           | have seen at least a handful of them.
        
           | IshKebab wrote:
           | So this assumes knowledge of an obscure theoretical
           | programming language, _and_ a dubious symbol replacement.
           | Yeah...
        
           | postepowanieadm wrote:
           | ^\
        
         | hillcapital wrote:
         | 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...
        
           | anacrolix wrote:
           | Boooo
        
           | masijo wrote:
           | Jesus, why? This is a bummer.
        
           | hajile wrote:
           | Pretty much all of those changes look bad to me.
        
           | trescenzi wrote:
           | oh wow it went from being a very clear language to looking
           | more like a hodgepodge of a few different languages.
        
           | IshKebab wrote:
           | Ah great improvements! I don't know why the sibling comments
           | are so negative; this is clearly better.
        
             | tasuki wrote:
             | Why? I'm used to \ meaning lambda. I understand you aren't,
             | and that's fine. But it's just your weird opinion
             | determined by what programming languages you've learned.
             | 
             | Ultimately, it's just syntax and not so important.
             | Semantics are important.
        
               | IshKebab wrote:
               | > Why? I'm used to \ meaning lambda.
               | 
               | 1. I know what lambda calculus is, and I didn't even make
               | the connection between \ and lambda. It's pretty tenuous.
               | 
               | 2. Most programmers do not know what lambda calculus is.
               | This is supposed to be a friendly language, not an
               | obscure academic one.
               | 
               | 3. It's not even the same lambda as in lambda calculus,
               | e.g. it takes multiple arguments.
               | 
               | 4. Lambda was a reasonable choice in lambda calculus
               | since it's a very "mathsy" language, and it's pretty much
               | the only symbol in the language. It's a pretty awful
               | choice for a practical programming language though -
               | there's a reason 99% of languages use something like `fn`
               | or `fun` or `function` or `def` instead of lambda to
               | define top-level functions.
               | 
               | I'm not a _huge_ fan of `|foo|` either to be honest - I
               | don 't see why you can't simply use the same syntax for
               | anonymous and named functions - but it is at least a
               | little better.
               | 
               | If it were up to me I'd go with something like
               | fn double(a: list[int]) -> list[int] {
               | a.map(fn(i) { i * 2 })       }
               | 
               | Same syntax; just allow omitting the name and inferring
               | the types. I can't recall any languages that do that
               | though so maybe there's some tricky reason it can't work?
        
               | Hasnep wrote:
               | Roc does use the same syntax for anonymous and named
               | functions, both before and after the recent syntax
               | changes.
        
               | trescenzi wrote:
               | Right now I'm in between liking Gleam or Roc for a hobby
               | functional language. The syntax you wrote is Gleam[1],
               | well aside from it being List(). It's very approachable,
               | very consistent and that's a core goal.
               | 
               | Roc was appealing because it was slightly more distinct
               | and more unique. Plus it was more focused on speed. I
               | appreciate them wanting to become more approachable. The
               | new syntax seems less approachable to me because it's now
               | a half step between approachable Haskell and what feels
               | like a combination of Ruby and Python.
               | 
               | [1]: https://gleam.run/
        
               | pmarreck wrote:
               | > Most programmers do not know what lambda calculus is
               | 
               | I would frankly be shocked if a 4 year syllabus in CS
               | these days just _skipped_ any mention of Alonzo Church,
               | especially considering that it 's fundamental to
               | functional programming and theoretical computer
               | science...
               | 
               | Maybe it's not taught in "CS" programs that are actually
               | just "practical software engineering" bootcamps with
               | extra steps. The real nerds know about lambdas. They're
               | even literally called that in Ruby (and possibly other
               | languages).
        
               | akkad33 wrote:
               | There can't be a more democratized language than Python
               | and in Python closures are defined literally using lambda
               | keyword
        
               | akkad33 wrote:
               | I think because a closure is not a function as a closure
               | can capture its environment, in a way that functions
               | can't, so using the same syntax for closures and
               | functions can be misleading (even though languages like
               | JS do it)
        
         | LAC-Tech wrote:
         | Opposite effect one, lost interest in Roc after reading that.
         | 
         | If anything I don't think Haskell goes far enough the automatic
         | currying, points free stuff. If you're going to be declarative,
         | don't half ass it.
        
         | hajile wrote:
         | I feel that he got a lot of pressure from the FP community and
         | wrote a bunch of nonsense instead of being straightforward with
         | them.
         | 
         | The only relevant reason he lists is point-free, but he doesn't
         | go far enough. Point-free very often turns into write-only
         | balls of unmaintainable nastiness. Wanting to discourage this
         | behavior is a perfectly reasonable position. Unfortunately,
         | this one true argument is given the most tepid treatment of all
         | the reasons.
         | 
         | Everything else doesn't hold water.
         | 
         | As he knows way better than most, Elm has auto-curry and has
         | been the inspiration for several other languages getting better
         | error messages.
         | 
         | Any language with higher-order functions can give a function as
         | a result and if you haven't read the docs or checked the type,
         | you won't expect it. He left higher-order function in, so even
         | he doesn't really believe this complaint.
         | 
         | The argument about currying and pipe isn't really true. The
         | pipe is static syntax known to the compiler at compile time.
         | You could just decide that the left argument is applied/curried
         | to the function before the right argument.
         | 
         | I particularly hate the learning curve argument. Lots of great
         | and necessary things are hard to learn. The only question is a
         | value judgement about if the learning is worth the payoff. I'd
         | guess that most of the Roc users already learned about currying
         | with a more popular FP language before every looking at Roc, so
         | I don't think this argument really applies here (though I
         | wouldn't really care if he still believed it wasn't worth the
         | learning payoff for the fraction of remaining users).
         | 
         | To reiterate, I agree with his conclusion to exclude currying,
         | but I wish he were more straightforward with his one good
         | answer that would tick off a lot of FP users rather than
         | resorting to a ton of strawman arguments.
        
           | throwaway2037 wrote:
           | No trolling/nitpicking from me: You wrote <<The only relevant
           | reason he lists is point-free>>. What do you mean by "point-
           | free"... or did you write "point three" and it was auto-
           | corrected on a mobile phone?
           | 
           | I also tried Googling for that term (never heard before), and
           | I found these:
           | https://stackoverflow.com/questions/944446/what-is-point-
           | free-style-in-functional-programming
           | https://en.wikipedia.org/wiki/Tacit_programming
           | 
           | If you really meant "point-free", can you tell me where in
           | his post he mentions it? I would like to learn more.
        
             | syockit wrote:
             | It's in the FAQ. Someone else posted a link to it in the
             | comments, check it out. And yes, it is about tacit
             | programming.
        
             | hajile wrote:
             | Point-free is a functional programming style where you
             | avoid assignments and prefer to do everything as a group of
             | nested, mapped, and composed functions. It relies heavily
             | on partial application. Like everything, it can be good
             | when used in moderation.
             | 
             | Here's a made-up JS example. I've attempted to be fair to
             | both approaches doing it how I personally would with each.
             | //typical implementation         const howManyAdults =
             | (data) => {           const adults = data
             | .flatMap(obj => obj.type === 'parent' ? [obj,
             | ...obj.children] : obj)             .filter(obj => typeof
             | obj.age === 'number')             .filter(obj => obj.age >=
             | 18 && obj.age < 150)                adults.forEach(adult =>
             | console.log(`${adult.name} is an adult age ${adult.age}`)
             | )                return adults.length         }
             | //nice "point-free" implementation using helper functions
             | const transformData = obj => obj.type === 'parent' ? [obj,
             | ...obj.children] : [obj]         const isAdult = obj =>
             | obj.age >= 18 && obj.age < 130              const
             | howManyAdults = pipe(           flatMap(transformData),
             | filter(hasTypeOf('age', 'number'),
             | filter(isAdult),           logEach`${pick('name')} is an
             | adult age ${pick('age')}`,           len,         )
             | //completely point-free gets crazy         const
             | howManyAdults = pipe(           flatMap(ifElse(
             | compose(eq('parent'), pick('type')),
             | juxt([identity, pick('children']),             identity,
             | ), []),           filter(hasTypeOf('age', 'number'),
             | filter(both(gte(pick('age',18), lt(pick('age'), 130)))),
             | logEach`${pick('name')} is an adult age ${pick('age')}`,
             | len,         )
             | 
             | I went through a point-free phase early in my career, but
             | even with lots of practice, I can't believe that most devs
             | ever find the third example as readable as the first or
             | second. I'd also note that this is a trivial example and
             | doesn't require you to track any monad wrappers either.
             | 
             | Personally, I rather like reading the moderate middle
             | example because it removes the boilerplate and allows me to
             | easily follow the overall flow without getting caught up in
             | the details. But I'll take the first example every time if
             | it means never dealing with the third example.
        
               | zozbot234 wrote:
               | inb4 pointless programming is pointless
        
         | msla wrote:
         | > `\\` for anonymous functions
         | 
         | A one-character ASCII rendering of the Greek lowercase letter
         | lambda: l
         | 
         | lx - x + 5
         | 
         | \x -> x + 5
        
         | pmarreck wrote:
         | > \ for anonymous functions
         | 
         | this didn't faze me in the least because it's just a more
         | easily typed l, the lambda character, which has for a long time
         | now (many decades) been used to describe anonymous functions
         | (i.e. "lambdas")
         | 
         | did you never take any formal CS education? if not, that might
         | explain it
         | 
         | so before you jump to calling it "dumb", maybe next time lean
         | on Chesterton's Fence for a bit.
         | 
         | https://sproutsschools.com/chesterton-fence-dont-destroy-wha...
         | 
         | That said, granted, the fact that it's also the escape
         | character is problematic. Maybe /\ might have been better but
         | that's even _harder_ to type.
        
         | rtfeldman wrote:
         | We recently changed Roc's lambda syntax from the syntax that
         | languages like Elm and Haskell use...                   foo =
         | \arg1, arg2 ->             body
         | 
         | ...to this:                   foo = |arg1, arg2|
         | body
         | 
         | The reason for this change was that we have a new and extremely
         | well-received language feature (landed but not yet formally
         | announced) which results in `->` and `=>` having different
         | meanings in the type system. This made it confusing to have
         | `->` in the syntax for anonymous functions, because it seemed
         | to suggest a connection with the type-level `->` that wasn't
         | actually there.
         | 
         | The most popular syntax that mainstream languages use today for
         | anonymous functions is something like `(arg1, arg2) => body`
         | but of course that has the same problem with having an arrow in
         | it, so changing to that wouldn't have solved the problem.
         | 
         | Rust uses `|arg1, arg2| body` (and Ruby kinda uses it too for
         | blocks), and we'd all had fine experiences using that syntax in
         | Rust, so we chose it as the new lambda syntax. You can see the
         | new syntax in the code example at the top of roc-lang.org.
        
         | HackerThemAll wrote:
         | Yeah Rust compiles slowly, so we need two more half-baked
         | languages - Zig and Roc, both of which I couldn't care less.
         | 
         | Rust's slow compilation comes from lots of features and an
         | excellent generated machine code quality. Both Zig and Roc will
         | be equally slow or slower if they match what Rust offers.
         | 
         | If all they want is fast compilation, they can just try Pascal.
        
       | greener_grass wrote:
       | 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 wrote:
         | > If FP isn't good for writing a compiler, what _is_ it good
         | for?
         | 
         | Summing the Fibonacci sequence I guess.
        
           | agumonkey wrote:
           | other FP languages bootstrapped onto themselves IIRC
        
           | incrudible wrote:
           | FP is _bad_ for computing the Fibonacci series unless you
           | have the compiler optimization to turn it into a loop (as
           | seen in imperative languages).
           | 
           | To be fair, most practical FP languages have that, but I
           | never saw the appeal for a strictly functional _general
           | purpose_ language. The situations where I wished one could
           | not use imperative constructs are very domain specific.
        
         | whlr wrote:
         | According to [1], they want to use a systems-level language for
         | performance.
         | 
         | [1] https://www.roc-lang.org/faq#self-hosted-compiler
        
           | tialaramex wrote:
           | "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.
        
             | WD-42 wrote:
             | At this point it feel like the are just playing with
             | languages.
        
               | munificent wrote:
               | I mean, the language doesn't even have a version number
               | yet. We should expect them to still be exploring the
               | design space.
        
           | pjmlp wrote:
           | "Unix system programming in OCaml"
           | 
           | https://ocaml.github.io/ocamlunix/ocamlunix.html
        
         | munchler wrote:
         | As an FP fan, I agree. This is disappointing.
        
         | kristoff_it wrote:
         | 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 wrote:
           | So why is it a non-goal of Roc to be implemented with this
           | approach?
        
             | coffeeaddict1 wrote:
             | Have you not read the post? Because compile times. Rust has
             | awful compile times. If it didn't, I'm sure the Roc team
             | would have stayed with Rust.
        
               | greener_grass wrote:
               | Yes, I read the post.
               | 
               | I don't understand why the goal is not to (eventually)
               | implement Roc in Roc, maybe with a dash of something else
               | for the "platform".
               | 
               | Roc is pitched as a general purpose functional
               | programming language with great performance.
               | 
               | How does a compiler not fall under this category?
        
               | Hasnep wrote:
               | Roc is pitched as having great performance _for a GC 'd
               | language_, that is, on par with Java, Go, C# instead of
               | Ruby, Python, JS. The Roc compiler team are looking for
               | C, C++, Rust, Zig kind of performance. Roc will, by
               | design, never reach that kind of speed.
        
               | greener_grass wrote:
               | We already have many great GC'd functional languages at
               | that performance level.
               | 
               | I first learned about Roc from this talk:
               | 
               | https://www.youtube.com/watch?v=vzfy4EKwG_Y
               | 
               | That's a niche that is not currently filled (well, maybe
               | MLTon) and that has me very excited! I'm sure I'm not
               | alone here.
        
           | bhansconnect wrote:
           | https://www.roc-lang.org/faq.html#self-hosted-compiler
        
         | chubot wrote:
         | That's an interesting point, and something I thought of when
         | reading the parser combinator vs. recursive descent point
         | 
         | Around 2014, I did some experiments with OCaml, and liked it
         | very much
         | 
         | Then I went to do lexing and parsing in OCaml, and my
         | experience was that Python/C++ are actually better for that.
         | 
         | Lexing and parsing are inherently stateful, it's natural to
         | express those algorithms imperatively. I never found parser
         | combinators compelling, and I don't think there are many big /
         | "real" language implementations that uses them, if any. They
         | are probably OK for small languages and DSLs
         | 
         | I use regular expressions as much as possible, so it's more
         | declarative/functional. But you still need imperative logic
         | around them IME [1], even in the lexer, and also in the parser.
         | 
         | ---
         | 
         | So yeah I think that functional languages ARE good for writing
         | or at least prototyping compilers -- there are a lots of
         | examples I've seen, and sometimes I'm jealous of the
         | expressiveness
         | 
         | But as far as writing lexers and parsers, they don't seem like
         | an improvement, and are probably a little worse
         | 
         | [1] e.g. lexer modes -
         | https://www.oilshell.org/blog/2017/12/17.html
        
           | greener_grass wrote:
           | OCaml allows mutation via reference cells.
        
             | chubot wrote:
             | I know that, and obviously you can write a recursive
             | descent parser in OCaml
             | 
             | But I'm saying there's nothing better about it than doing
             | it in OCaml vs. C++ or Python -- it's the same or a little
             | worse
             | 
             | IMW it's natural to express the interface to a lexer and
             | parser as classes -- e.g. you peek(), eat(), lookahead(),
             | etc.
             | 
             | Classes being things that control mutation
             | 
             | But objects in OCaml seem to be a little separate dialect:
             | https://dev.realworldocaml.org/objects.html
             | 
             | When I debug a parser, I just printf the state too, and
             | that is a little more awkward in OCaml as well. You can
             | certainly argue it's not worse, but I have never seen
             | anyone argue it's better.
             | 
             | ---
             | 
             | Culturally, I see a lot of discussions like this, which
             | don't really seem focused on helping people finish their
             | parsers:
             | 
             | https://discuss.ocaml.org/t/why-a-handwritten-parser/7282/7
             | 
             | https://discuss.ocaml.org/t/good-example-of-handwritten-
             | lexe...
             | 
             | I also use lexer/parser generators, and I like that there
             | are more tools/choices available in C/Python than in OCaml.
        
         | isaacvando wrote:
         | Roc couldn't be optimized for writing the Roc compiler without
         | sacrificing some of its own goals. For example, Roc is
         | completely memory-safe, but the compiler needs to do memory-
         | unsafe things. Introducing memory-unsafety into Roc would just
         | make it worse. Roc has excellent performance, but it will never
         | be as fast as a systems language that allows you to do manual
         | memory management. This is by design and is what you want for
         | the vast majority of applications.
         | 
         | There are a number of new imperative features that have been
         | (or will be) added to the language that capture a lot of the
         | convenience of imperative languages without losing functional
         | guarantees. Richard gave a talk about it here:
         | https://youtu.be/42TUAKhzlRI?feature=shared.
        
           | Muromec wrote:
           | >but the compiler needs to do memory-unsafe things
           | 
           | sorry, but why?
        
             | isaacvando wrote:
             | I believe the main reason is for achieving the best
             | possible performance. Someone closer to the compiler could
             | give more detail.
        
             | vitiral wrote:
             | It's not just the lang but the std lib too
             | 
             | https://www.roc-lang.org/faq#rust-and-zig
        
             | mrkeen wrote:
             | I am also skeptical.
             | 
             | A compiler is a function from source code strings to binary
             | bytes. Writing out instructions to do memory-unsafe things
             | is not in itself a memory-unsafe activity.
        
           | int_19h wrote:
           | It still feels kinda weird. Parsers, compilers etc are
           | traditionally considered one of the "natural" applications
           | for functional programming languages.
        
           | pjmlp wrote:
           | There are plenty of compilers written in memory safe
           | languages, including the list of self hosted ones linked from
           | the gist describing the rewrite.
        
       | chambers wrote:
       | 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.
        
       | debugnik wrote:
       | > 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 wrote:
         | 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.
        
         | bhansconnect wrote:
         | This is more about simplicity, maintainability, and possiblity
         | for new contributors to easily jump in and fix things. Our
         | current parser is not fun for new contributors to learn. Also,
         | I think parser combinators obsficate a lot of the tracking
         | required for robust error messages.
         | 
         | Personally, I find parser combinators nice for small things but
         | painful for large and robust things.
        
       | flooow wrote:
       | 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.
        
         | bhansconnect wrote:
         | Zig was not ready or nearly as popular back in 2019 when the
         | compiler was started.
         | 
         | Not to mention, Richard has a background mostly doing higher
         | level programming. So jumping all the way to something like C
         | or Zig would have been a very big step.
         | 
         | Sometimes you need a stepping stone to learn and figure out
         | what you really want.
        
         | christophilus wrote:
         | It's covered in TFA, but the tldr is they started when Zig was
         | immature.
        
         | norman784 wrote:
         | > The real question I have is why he chose Rust in the first
         | place.
         | 
         | If you read the linked post carefully you will know.
         | 
         | > Compile times aside, the strengths and weaknesses of Rust and
         | Zig today are much different than they were when I wrote the
         | first line of code in Roc's Rust compiler in 2019. Back then,
         | Rust was relatively mature and Zig was far from where it is
         | today.
        
       | zoogeny wrote:
       | 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 wrote:
         | 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.
        
           | fc417fc802 wrote:
           | 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.
        
             | valorzard wrote:
             | https://github.com/carp-lang/Carp
        
             | throwawaymaths wrote:
             | posted yesterday:
             | 
             | https://news.ycombinator.com/item?id=42923829
        
           | pcwalton wrote:
           | > 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.
        
             | zamalek wrote:
             | > + Reference counting is a form of garbage collection.
             | 
             | I agree with Raymond Chen's take on the academic definition
             | of GCs[1], and therefore Rust is certainly a GC'd language
             | (because your code behaves as though memory is infinite...
             | usually). It's probably one of the first examples of
             | "static garbage collection" - though I'm sure someone will
             | point out a prior example.
             | 
             | [1]: https://devblogs.microsoft.com/oldnewthing/20100809-00
             | /?p=13...
        
               | jonahx wrote:
               | This feels like deliberate misdirection, because in most
               | practical cases what people mean is "some memory
               | management process that will slow my program down non-
               | trivially". By this definition Rust does not have GC
               | whereas Go, eg, does.
               | 
               | The "simulates infinite RAM" is an interesting
               | perspective but simply not the subject of most
               | conversations.
        
               | zozbot234 wrote:
               | Manual heap allocation can slow the program down non-
               | trivially compared to using an arena which is cleaned up
               | all at once; hence, manual heap allocation is a kind of
               | GC. Checkmate atheists.
        
               | caspper69 wrote:
               | I went down a path researching the viability of region
               | based memory management (a form of arenas).
               | 
               | A language based on such a paradigm can be provably
               | memory safe, and regions can have their own allocators
               | and optionally provide locking when the regions are
               | shared.
               | 
               | This approach obviates the need for reference counting
               | individual allocations (since regions are tracked as a
               | whole), but it suffers from excess memory usage in the
               | event of many short-lived allocations (i.e. they leak
               | until the entire region's allocations go out of scope).
               | But those types of memory accesses can be problematic in
               | every systems language as they can eventually cause
               | memory fragmentation.
               | 
               | That problem can be minimized using per-allocation
               | reference counting, but that can incur a heavy
               | performance hit. Although not having to use it everywhere
               | could minimize the impact.
               | 
               | The plus side is you don't have to worry about borrow
               | checking, so such a language can be more flexible than
               | Rust, while still maintaining the memory safety aspect.
               | 
               | The question, as always, is: is the juice worth the
               | squeeze?
               | 
               | Truthfully, I suspect no. The Rust train has left the
               | station and has a decade head start. Even if it is a pain
               | in the ass, lol.
        
               | zozbot234 wrote:
               | You may be interested in Rust language proposals for
               | local memory allocators and "storages"; they may be
               | enough for something very much like this. The lifetime
               | concept in Rust is quite close already to that of a
               | "region", i.e. an area of memory that the lifetime can
               | pertain to.
        
               | caspper69 wrote:
               | Depending on the semantics of the implementation,
               | something like that would go a long way toward
               | eliminating one of my biggest issues with Rust. For a
               | low-level systems language, it is imperative to offer 2
               | things, which are currently a pain in Rust: (1) you must
               | be able to "materialize" a struct at an arbitrary
               | location; why? Because hardware tables _exist_ at a
               | specified location and are provided by hardware- they are
               | not created or instantiated in the host language; and (2)
               | be able to reference structs from other structs, which
               | immediately triggers lifetime annotations, which begin to
               | color everything they touch, must like async does to
               | functions.
               | 
               | And I admit, I loathe the borrow checker. Ironically, I
               | never really have problems with it, because I do
               | understand it, it's just that I find it too _limiting_.
               | Not everything I want to do is unsafe, and I hate the way
               | it has made people think that if you really do know
               | better than the borrow checker, you must clearly be doing
               | something wrong and you should re-architect your code. It
               | 's insulting.
        
               | steveklabnik wrote:
               | What's old is new again. Cyclone, one of the influences
               | on Rust, is a systems language using regions for memory
               | management.
        
               | another2another wrote:
               | >Manual heap allocation can slow the program down non-
               | trivially compared to using an arena
               | 
               | But GC has nothing to do with whether heap allocations
               | 'slow the program down', it's who owns the lifetime of
               | the allocated object - for GC not the programmer, but the
               | runtime.
               | 
               | If I create a an object, and then then soon after deref
               | it [MyObj release], then I _know_ it will dealloc
               | immediately after. I 'm basically in control of its
               | lifetime, even though it's ref counted.
               | 
               | If I call [MyObj free] and it's still owned by another
               | object (e.g. I added it to some collection), _that 's OK_
               | because the object is still useful and has a lifetime
               | outside of my control, and its destruction will be
               | deferred until it doesn't.
               | 
               | But, with a GC object, if I call new MyObj() and then
               | soon after try my best to destroy it, I can't because I'm
               | not in control of its lifetime, the runtime is.
               | 
               | That's what I see the distinction between GC and ref
               | counted (not GC), and why I mostly don't agree with so
               | many people here insisting that ref counting is garbage
               | collection. How can it be when I can easily be explicitly
               | in control of an objects lifetime? I create it, then I
               | destroy it, and it happens exactly in the sequence that I
               | dictate.
               | 
               | For sure, ARC makes it a bit more subtle, but even then,
               | I can reliably predict when an object will be destroyed
               | and factor that into the sequence of events in my
               | program.
               | 
               | -An Atheist.
        
               | nemetroid wrote:
               | By that definition, a C++ program with heavy usage of
               | std::shared_ptr has GC.
        
               | cmrdporcupine wrote:
               | And it does. Reference counting is garbage collection.
               | And std::shared_ptr, or Rust's Rc/Arc are basically
               | lightweight GC runtimes inside your program.
        
               | coldtea wrote:
               | Isn't that the point?
        
               | nemetroid wrote:
               | I don't think it's the point of the comment I replied to,
               | no.
        
               | imtringued wrote:
               | By this logic you're writing the garbage collector by
               | hand in C.
        
             | hansvm wrote:
             | It's not a perfect analogy, but if you want to put yourself
             | in the shoes of the people making it:
             | 
             | 1. Rust is an immensely complicated language, and it's not
             | very composable (see the async debacle and whatnot). On the
             | simple<->complex slider, it's smack dab on the right of the
             | scale.
             | 
             | 2. Ignoring any nitpicking [0], Zig is memory-safe enough
             | in practice, placing it much closer to Rust than to C/C++
             | on the memory safety axis. My teammates have been using Zig
             | for nearly a year, and the only memory safety bug was (a)
             | caught before prod and (b) not something Rust's features
             | would have prevented [1]. The `defer` and `errdefer`
             | statements are excellent, and much like how you closely
             | audit the use of `unsafe` in Rust there is only a small
             | subset of Zig where you actually need to pull your
             | magnifying glass out to figure out if the code has any
             | major issues. In terms of memory issues I've cared about
             | (not all conforming to Rust's narrow definition of memory
             | safety), I've personally seen many more problems in Rust
             | projects I contribute toward (only the one in Zig, plus a
             | misunderstanding of async as I was learning the language a
             | few years ago, many of varying severity in Rust, at this
             | point probably more code written in Zig than Rust, 10yoe
             | before starting with either).
             | 
             | With that in mind, you have C/C++ on the unsafe axis and
             | Zig/Rust on the safe axis. The complexity axis is self-
             | explanatory, fleshing out the analogy.
             | 
             | Is Zig memory-safe? No, absolutely not. Does that mean that
             | Rust will win out for some domains? Absolutely. In
             | practical terms though, your average senior developer will
             | have many memory safety bugs in C/C++ and few in Zig/Rust.
             | It's a reasonable way to compare and contrast languages.
             | 
             | Is it a perfect description? No, the map is not the
             | territory. It's an analogy that helps a lot of people
             | understand the world around them though.
             | 
             | [0] Even Python is simpler than Rust, and it's memory-safe.
             | If we're limiting ourselves to systems languages, you still
             | have a number of options like Ada and Coq. Rust is popular
             | because it offers a certain tradeoff in the
             | safety/performance/devex Pareto curve, and because it's had
             | a lot of marketing. It's unique in that niche, by
             | definition, but it's far from the only language to offer
             | the features you explicitly stated.
             | 
             | [1] It was just an object pool, and the (aggregate)
             | resetting logic wasn't solid. The objects would have passed
             | through the borrow checker with flying colors though.
             | 
             | Edit: To your GC point, many parts of Rust look closer to
             | GC than not under the hood. You don't have a GC pause, but
             | you have object pools (sometimes falling back to kernel
             | object pools) and a variety of allocation data structures.
             | If RC is a GC tactic, the extra pointer increment/decrement
             | is negligible compared to what Rust actually does to handle
             | its objects (RC is everything Rust does, plus a counter).
             | That's one of my primary performance complaints with the
             | language, that interacting with a churn of small objects is
             | both expensive and the easiest way to code. I can't trust
             | code I see in the wild to behave reasonably by default.
        
               | pcwalton wrote:
               | I've been seeing C++ fans talk about how they never see
               | memory safety issues in practice in C++ for a decade and
               | a half. I even believed it sometimes. But if there's ever
               | been a common story over those 15 years, it's that these
               | anecdotes mean little, and the actual memory safety
               | property means a lot.
               | 
               | The only time I've seen "almost memory safe" actually
               | work is in Go and Swift, which have memory safety
               | problems with concurrency, but they're actually rare
               | enough not to matter too much (though in Go's case it
               | would have been easy to design interfaces and slices not
               | to have the problem, and I wish they had). I simply don't
               | believe that Zig is meaningfully more memory safe than
               | C++.
        
               | fweimer wrote:
               | I think it's possible to retrofit race-safe slices and
               | interfaces into Go, and I expect it to happen one day
               | once some actually relevant code execution exploit shows
               | up.
               | 
               | There's going to be some impact and low-level libraries
               | that manipulate directly the words that constitute slices
               | and interfaces, and there will some slight performance
               | impact and increase in memory usage, but hopefully
               | nothing drastic.
        
               | zozbot234 wrote:
               | I think slices and interfaces in Go are both 2xusize
               | width, in which case you just need double-width CAS to
               | make them safe from data races - which most modern
               | architectures support.
        
               | fweimer wrote:
               | Slices are base pointer, length, and capacity, so three
               | words. But there's a garbage collector, so you can
               | install a thunk if the slice is updated in a way that
               | torn reads cause problems. It makes reads slightly
               | slower, of course.
               | 
               | Two-word loads could be used for interface values
               | (assuming that alignment is increased), except if support
               | older x86-64 is needed. There are implementations that
               | require using CMPXCHG16B, which is a really slow way to
               | load two words. Both Intel and AMD updated their ISA
               | manuals that using VMOVDQA etc. is fine (once the CPU
               | supports AVX and the memory is cacheable).
        
               | AndyKelley wrote:
               | I don't see any Zig repositories under
               | https://github.com/pcwalton
               | 
               | Is your opinion based on anything other than pure
               | speculation?
               | 
               | I think it makes more sense to form an opinion after
               | actually having tried Rust, C++, and Zig in earnest.
               | 
               | There are lots of us out there who've done it. Join us!
        
               | FpUser wrote:
               | >"I've been seeing C++ fans talk about how they never see
               | memory safety issues in practice in C++ for a decade and
               | a half. I even believed it sometimes. But if there's ever
               | been a common story over those 15 years, it's that these
               | anecdotes mean little, and the actual memory safety
               | property means a lot."
               | 
               | While I use C++ a lot I am not a fan. It is just one of
               | many languages I use. But from my personal experience it
               | is true. I frankly forgot when was the last time I hit
               | memory problem, years for sure. And my code is often a
               | stateful multithreaded backends with high request rate.
        
               | imtringued wrote:
               | Are you properly trying to exploit your own software?
               | 
               | If you're not looking, how would you know?
               | 
               | You could have a blatant SQL injection in your code and
               | you can always pretend that it doesn't matter, since you
               | haven't been attacked so far.
        
               | jeremyjh wrote:
               | Memory safety issues show up all the time outside of
               | security exploits. Industry began pursuing memory safety
               | long before anyone cared much about security, simply
               | because of the productivity impact of chasing down memory
               | leaks and use-after-free bugs. So if they've used C++ for
               | years without having to do that, its pretty meaningful.
               | It also matches my experience working on a large C++
               | application that had ubiquitous use of smart pointers. I
               | wouldn't want to do that again, but RAII takes you a long
               | way.
        
               | zozbot234 wrote:
               | > see the async debacle and whatnot
               | 
               | The async featureset in Rust is far from complete, but
               | async is also somewhat of a niche. You're not necessarily
               | expected to use it, often you can just use threads.
               | 
               | > Zig is memory-safe enough in practice
               | 
               | Temporal safety is a huge deal, especially for the
               | "programming in the large" case. Where unstated
               | assumptions that are relied upon for the safety of some
               | piece of code can be broken as some other part of the
               | code evolves. The Rust borrow checker is great for
               | surfacing these issues, and has very few practical
               | alternatives.
               | 
               | > If we're limiting ourselves to systems languages, you
               | still have a number of options like Ada and Coq.
               | 
               | It's easy to be "safe" if the equivalent to free() is
               | marked as part of the unsafe subset, as with Ada. Coq is
               | not very relevant on its own, though I suppose it could
               | be part of a solution for proving the memory safety of C
               | code. But this is known to be quite hard unless you do
               | take your care to write the program in the "idiomatically
               | safe" style that a language like Rust points you to.
        
               | rastignack wrote:
               | > The async featureset in Rust is far from complete, but
               | async is also somewhat of a niche. You're not necessarily
               | expected to use it, often you can just use threads.
               | 
               | I'm sorry but it's not true. You lose access to most of
               | the ecosystem.
        
               | Ygg2 wrote:
               | > On the simple<->complex slider, it's smack dab on the
               | right of the scale.
               | 
               | Sure, but now you snuck in an Artifact of Death (in
               | TvTropes sense) into your codebase. It won't kill your
               | code base immediately and with proper handling it might
               | work, but all it takes is one mistake, one oversight, for
               | it to cause issues.
        
               | hansvm wrote:
               | I agreed with you either way, but I'm currently at a loss
               | as to whether this is a for/against take on rust.
        
               | Ygg2 wrote:
               | You traded ease of writing for ease of long term ease of
               | debugging, I don't think we agree.
        
               | throwawaymaths wrote:
               | even so it seems like it would eventually be possible to
               | do more safety analysis for zig, if not in the compiler
               | itself:
               | 
               | https://github.com/ityonemo/clr
        
               | emporas wrote:
               | > 1. Rust is an immensely complicated language, and it's
               | not very composable.
               | 
               | It is a procedural language and as such, composition of
               | functions is not implemented easily, if at all possible.
               | It is a shame for sure that such powerful techniques are
               | not possible in Rust, but for some people it is worth the
               | trade off.
        
               | zozbot234 wrote:
               | It is implemented. But it requires quite a bit of
               | boilerplate if you want to compose arbitrary closures at
               | runtime (as you would in most FP languages), because that
               | involves non-trivial overhead and Rust surfaces it in the
               | code (see "dyn Fn trait objects" for how that works in
               | detail).
        
               | emporas wrote:
               | Yes i know, i have wrote some FnMut closures muself. I
               | meant, function composition should work like Lisp or
               | Haskell, it should be very easy and intuitive, no
               | boilerplate also. Closures in Rust, feel a lot like a
               | hack compared to functional languages.
               | 
               | The way i put it, is that Haskell is a language with very
               | strict type system, while Rust has very strict type
               | system, and strict scoping. Strict scopes mean that an Fn
               | closure has to be different from a FnMut closure, which
               | also means several other complications when it comes to
               | async.
               | 
               | This trade off is fine with me, but for several other
               | people it doesn't worth it.
        
               | zozbot234 wrote:
               | There's additional boilerplate involved if you want your
               | closures to keep their captured variables around beyond
               | their original scope in the program; in Rust, that's
               | implemented as a kind of shared ownership which involves
               | Rc<> or Arc<>. FP languages rely on program-wide GC for
               | this, which of course has significant overhead of its
               | own.
        
               | emporas wrote:
               | Closures are definitely cumbersome in Rust, and
               | Lisp/Haskell/Scala programmers use them all the time. In
               | SICP for example, they translate several math equations
               | to code using higher order functions and closures, and it
               | is wonderful how clean the code is, and how close to the
               | actual mathematics.
               | 
               | That's what i meant it is impossible to do in Rust. From
               | that point of view, Rust is a low level procedural
               | language, but expressing any kind of business logic it is
               | almost as high level as Haskell or Java.
               | 
               | But if we focus on error detection, then Rust is the
               | highest level of any other PL. For example Java or Python
               | are too low level when an error occurs. That high level
               | of error detection is paid of course, and that is by
               | longer compilation times.
               | 
               | If i had a wish though, i would wish Rust had as good
               | closures as Haskell or Lisp.
        
               | zozbot234 wrote:
               | In principle you could fix any lack of syntactic sugar
               | (which is what leads to the "clean code" feel in Scheme
               | or Haskell - but even Swift has custom sugar of its own
               | for refcounting and copy-on-write) with a custom macro -
               | which would be entirely optional, triggered by a custom
               | attribute such as #[sloppy_code]. But that still requires
               | a lot of fiddly implementation work.
        
             | tialaramex wrote:
             | Today all of the code I'm not paid to write is in Rust. I
             | spent many happy years previously getting paid to write C
             | (I have also been paid to write Java, PHP, Go and C#, and I
             | have written probably a dozen more languages for one reason
             | or another over the years but never as specifically a thing
             | people were paying me to do)
             | 
             | I always thought C++ was a terrible idea, from way before
             | C++ 98, I own Stroustrup's terrible book about his
             | language, which I picked up at the same time as the revised
             | K&R and it did nothing to change that belief, nor have
             | subsequent standards.
             | 
             | However, I do have some sympathy for this sentiment about
             | Rust being a better C++. Even though Rust and C++ have an
             | entirely different approach to many important problems the
             | syntax often looks similar and I think Zig manages to be
             | less intimidating than Rust for that reason if you don't
             | want that complexity.
             | 
             | Personally I had no interest in C+++ and I have no serious
             | interest in Zig.
             | 
             | + Ironically I ended up caring a lot more about C++ _after_
             | I learned Rust, and most specifically when understanding
             | how Rust 's HashMap type works, but I didn't end up liking
             | C++ I just ended up much better informed about it.
        
             | munificent wrote:
             | Board games and craft beers are utterly unrelated objects
             | who have commonality on essentially no axes (except sitting
             | on tables, I guess). And, yet, if you like one, there's a
             | very good chance you like the other.
             | 
             | I think that's where the sentiment comes from. It's not
             | that Rust is similar to C++ in terms of the actual
             | languages and their features. It's that people who like C++
             | are morely likely to like Rust than people who like C are.
             | 
             | I would argue that C is not a minimalistic language either.
             | There is a _lot_ under the hood in C. But it _feels_ small
             | in a way that Rust and C++ don 't.
             | 
             | I think Rust and C++ appeal to programmers who are OK with
             | a large investment in wrapping their head around a big
             | complex language with the expectation that they will be
             | able to amortize that investment by being very productive
             | in large projects over a large period of time. Maybe
             | sometimes the language feels like trying to keep a piece of
             | heavy duty machinery from killing you, but they're willing
             | to wrestle with it for the power you get in return.
             | 
             | The people who are excited about Zig and C wants something
             | that feels more like a hand tool that doesn't demand a lot
             | of their attention and lets them focus on writing their
             | code, even if the writing process is a little more manual
             | labor in return.
        
               | estebank wrote:
               | > Maybe sometimes the language feels like trying to keep
               | a piece of heavy duty machinery from killing you, but
               | they're willing to wrestle with it for the power you get
               | in return.
               | 
               | It's funny because to me there's an analogy with heavy
               | machinery but materially different: there are some
               | industrial machines that have _two_ buttons that need to
               | be actuated to activate the mechanism, separated by arm
               | length in order to _ensure_ that the operator 's arms are
               | out of the way when the limb crunching bits are moving. I
               | see Rust that way, engineering the safe way to do things
               | as the path of least resistance, at the cost of some
               | convenience when trying to do something "unsafe".
        
               | incrudible wrote:
               | Okay, but now imagine a kitchen appliance that did the
               | same thing. It would not be a big seller. Of course a
               | kitchen appliance can injure and even kill you, but it
               | probably wouldn't unless you try really hard.
               | 
               | Most of programming is like that, but in the few cases
               | where there literally are lives at stake, memory safety
               | by itself will not do much for you and performance is
               | going to be a secondary concern.
               | 
               | Zig does have safety features that C/C++ do not have, but
               | also one should not underestimate the security
               | implications of language complexity by itself.
        
               | pcwalton wrote:
               | The reason I focus on the memory safety difference is
               | precisely to not minimize its importance. It's far more
               | salient of a difference than whether a language "feels
               | big" or not. Talking about whether Zig requires "a little
               | more manual labor" than Rust is missing the enormous
               | elephant in the room.
        
               | platinumrad wrote:
               | > It's far more salient of a difference than whether a
               | language "feels big" or not.
               | 
               | You clearly don't like it, but it seems many people
               | disagree.
        
               | throwawaymaths wrote:
               | pcwalton is responsible for a lot of the rust borrow
               | checker, so, not a neutral opinion. ive posted it too
               | many times on this thread but it seems borrow checking
               | analysis may be possible for zig (if the zig team should
               | want to)
        
               | pcwalton wrote:
               | I highly suspect it won't be feasible for the same reason
               | it isn't feasible in C++: you could technically implement
               | it, but tons of existing patterns in the ecosystem would
               | become impossible to express, so in practice it would end
               | up creating a different language. From a skim, the CLR
               | project you linked to claims that metadata will probably
               | be needed in order to enforce aliasable xor mutable, and
               | I agree.
        
               | zozbot234 wrote:
               | > tons of existing patterns in the [C/C++] ecosystem
               | would become impossible to express
               | 
               | Well, the really harsh way of putting this is that the
               | patterns break for a reason; they rely on global claims
               | about the program, so they aren't genuinely robust in the
               | context of code that sits within a large, constantly
               | evolving codebase that can't be practically surveyed in
               | its entirety. Rust is very good at picking patterns that
               | can be verified with a comparatively straightforward,
               | "local" analysis that broadly follows the same structure
               | as the actual program syntax. Safety claims that rely on
               | "global" properties which cannot be kept within a self-
               | contained, module-like portion of the code are
               | essentially what the unsafe marker is intended for. And
               | this is exactly what idiomatic C/C++ code often gives
               | you.
               | 
               | This is actually why I think that proposals like Safe C++
               | should get a lot more attention that they do at present.
               | Yes, Safe C++ changes what's idiomatic in the language
               | but it does so in a way that's broadly sensible (given
               | our increased attention to memory safety) especially in a
               | context of "programming in the large".
        
               | throwawaymaths wrote:
               | you can go a long way before getting to aliasable xor
               | mutable, and the metadata doesn't require a language
               | change, theres an example in there on how to bind
               | metadata with no language changes.
        
               | munificent wrote:
               | I think the people who like Rust are in a room where they
               | perceive that elephant to be enormous and people who like
               | Zig are in a room where they perceive it to be much
               | smaller.
               | 
               | You can certainly argue whether or not their perceptions
               | are correct, but I generally believe that people are
               | entitled to their priorities.
               | 
               | Either way, you initially stated confusion about why
               | people stated certain opinions about Rust, C++, and C. I
               | tried to explain why people might hold those opinins. You
               | are then arguing that they _shouldn 't_ hold those
               | opinions. Whether or not that's true, a prescriptive
               | claim is orthogonal to understanding what's actually in
               | their heads.
        
               | imtringued wrote:
               | The elephant is enormous, because the C crowd is not
               | living up to what they need to do to actually make the
               | lack of memory unsafety unimportant. C is like ruby in
               | the sense that the untyped nature of ruby might initially
               | buy you a productivity win, but in the long run it
               | requires you to dilligently write impeccable unit tests,
               | since even the most basic correctness checks can only be
               | done at runtime.
               | 
               | Actually that's wrong. In C you will need exhaustive
               | formal verification, because UB doesn't cause minor
               | miscompilation anymore. Formal verification is far more
               | onerous than whatever Rust is demanding.
        
               | tialaramex wrote:
               | > And, yet, if you like one, there's a very good chance
               | you like the other.
               | 
               | Among my friends I know several people who are very
               | enthusiastic about board games and several who are very
               | enthusiastic about craft beer, but there's not a
               | particular noticeable overlap. Personally of course I am
               | very into board games and I don't drink at all.
               | 
               | > I would argue that C is not a minimalistic language
               | either. There is a lot under the hood in C.
               | 
               | Nah, C actually is small, that's why K&R is such a short
               | book. It makes enormous compromises to pull that off, but
               | presumably on a machine where 64kB of RAM is
               | extraordinary these compromises made lots of sense. C23
               | is quite a bit bigger, for example "bool" is now an
               | actual type (albeit implicitly convertible) but still
               | small by modern standards.
               | 
               | There really isn't that much "under the hood", it's often
               | just the least possible moving parts that could possibly
               | have worked.
               | 
               | a[b] in C++ is a call to a member function
               | a.operator[](b) -- arbitrary user code
               | 
               | a[b] in Rust is a call to core::ops::Index::index(a, b)
               | or, in context IndexMut::index_mut -- again, arbitrary
               | user code
               | 
               | a[b] in C is just a pointer addition of a and b - one of
               | them will be converted to a pointer if necessary, and
               | then the other one is added to the pointer using normal
               | pointer arithmetic rules
        
               | hajile wrote:
               | > Nah, C actually is small,
               | 
               | I'd argue that C is much bigger than K&R, but that isn't
               | immediately visible to a new programmer because it's all
               | undefined behaviors.
        
               | pjmlp wrote:
               | C23 + compiler extensions versus K&R C, is a little more
               | than only UB.
        
               | pjmlp wrote:
               | Except C in 2025 isn't K&R C, rather C23.
               | 
               | Also even between C89 and C23, many folks wrongly count
               | "whatever my compiler does" as C, and there are endless
               | amounts of extensions to be aware of.
        
               | voidhorse wrote:
               | Exactly. There are two kinds of programmers, those who
               | enjoy spending a bunch of time thinking about problems
               | and decisions the language has foisted upon you
               | (subtyping hierarchies, lifetime annotations, visibility,
               | design patterns) and there are those that like spending
               | that time thinking about the actual problem they want to
               | solve instead.
               | 
               | I jest, but only a tiny bit. The features of heavy OOP
               | and feature-rich languages tend to show their value only
               | in really large codebases being worked on by several
               | different people--precisely because many of their
               | features are just guardrails to make it hard for people
               | to code incorrectly against another's understanding or
               | assumptions, when shared understanding is more difficult
               | to establish. Contrarily, any solo programmer or really
               | small team is almost invariably better served by a
               | language like go, C, scheme, or Zig.
        
               | pcwalton wrote:
               | The idea that memory safety is only, or primarily, a
               | problem in large codebases written by a sizable team is
               | an interesting theory (sort of an inverse Linus' Law?)
               | Unfortunately, it's contradicted by decades of
               | experience.
        
               | bornfreddy wrote:
               | Just to be clear, I liked memory handling in Rust. It was
               | the sheer size of the language that made it... not fun.
               | But borrow checker made sense.
        
               | lenkite wrote:
               | Go is pretty good for large, shared projects too - thanks
               | to its tooling, formalized best-practices and
               | comprehensive batteries-included standard library.
        
             | gens wrote:
             | It is not about memory safety or anything like that. It is
             | about simplicity.
             | 
             | If you say "you can't do x with y in C++" you will get an
             | "yes you can, you just use
             | asd::dsadasd::asdadqwreqsdwerig_hfdoigbhiohrf() with
             | weaorgoiawr flag". From what I have seen from Rust, it is
             | similar. I don't want to fill my brain with vim bindings..
             | cough.. Rust ways of doing something. I just want to code
             | my hobby game engine v7.
             | 
             | That said, I am happy to use software written in it. Even
             | though the evangelists can be really annoying.
        
             | coldtea wrote:
             | The similarity between C++ and Rust is that both bust your
             | balls with complexity for programming at large. And the
             | inverse goes for C and Zig.
             | 
             | Those are the axes relevant to the parent in the context of
             | their comment - not specific language semantics or core
             | features.
        
             | defen wrote:
             | > There is no corresponding popular replacement for C
             | that's more minimalist than Rust and memory safe.
             | 
             | In the real world, memory safety is not all-or-nothing
             | (unless you're willing to concede that Rust is not safe
             | either, since unsafe Rust exists). I'm working on an
             | embedded project in Rust and I'd MUCH rather be using Zig.
             | The only safety thing that Rust would give me that Zig does
             | not is protection from returning pointers to stack-
             | allocated objects (there are no dynamic allocations and no
             | concurrency outside of extremely simple ISRs that push
             | events onto a statically allocated queue). But in exchange
             | I have to deal with the presence of _unsafe_ Rust, which
             | feels like a gigantic minefield even compared to C.
        
               | zozbot234 wrote:
               | > But in exchange I have to deal with the presence of
               | unsafe Rust, which feels like a gigantic minefield even
               | compared to C.
               | 
               | I think idiomatic coding norms for unsafe Rust are still
               | a bit half-baked, and this is where something like Zig
               | can have an advantage of sorts. You can see this also,
               | e.g. in the ongoing proposals for a Pin<> alternative.
        
               | throwawaymaths wrote:
               | protection from returning stack pointers seems to be
               | detectable with static analysis of zig AIR.
               | 
               | https://github.com/ityonemo/clr
        
             | sesm wrote:
             | > There is no corresponding popular replacement for C
             | that's more minimalist than Rust and memory safe.
             | 
             | There is Objective-C, it fits your definition of memory
             | safety.
        
               | pcwalton wrote:
               | Objective-C and Swift are the reason why I added the
               | footnote. (Also Objective-C is very, very much not memory
               | safe.)
        
             | vitiral wrote:
             | From what I understand that language is Zig, no?
             | 
             | Also, there's FORTH!
        
               | wtetzner wrote:
               | I don't think Zig is memory safe?
        
               | vitiral wrote:
               | I was replying to this bit
               | 
               | > 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.
               | 
               | Edit: oh, I never read the last bit "and memory safe" --
               | well ya, that's kind of rust's major advantage.
        
             | bmacho wrote:
             | > > I was looking for a replacement for C, but Rust is
             | actually a replacement for C++. Totally different beast -
             | powerful but complex.
             | 
             | > 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.
             | 
             | Indeed. Let one axis be the simple/multi paradigm. Let the
             | other axis be no memory management / automatic memory
             | management without GC / GC. This divides the plane into 6.
             | In the simple + no memory management sits C and Zig, and in
             | the multiparadigm + memory safe without GC segment sits C++
             | and Rust.
             | 
             | > There is no corresponding popular replacement for C
             | that's more minimalist than Rust and memory safe.
             | 
             | Those are some weird requirements for "being a
             | replacement", but it is obviously true, as you picked them
             | such.
        
           | huijzer wrote:
           | I read a blog that called Rust a language that was aimed to
           | be high-level but without GC.
        
           | anacrolix wrote:
           | This is actually accurate. While Rust is a great replacement
           | for C, so is C++. But Rust has tons of extra features that C
           | doesn't have, just like C++. Moving from C++ to Rust is a
           | sideways move. Moving from C to Rust is definitely an
           | increase in complexity and abstraction.
           | 
           | Rust is a great replacement for C++ as it fits into the same
           | place in the stack of tools.
           | 
           | Go is not a C or Python replacement.
           | 
           | Zig _is_ a good replacement for C.
        
             | zozbot234 wrote:
             | > But Rust has tons of extra features that C doesn't have,
             | just like C++.
             | 
             | C++ has tons of extra features over C because it's a
             | kitchen sink language. Rust has _some_ extra features over
             | C because in order to support static analysis for memory
             | safety in a practically usable manner, you _need_ those
             | features. In practice, there are lots of C++ features that
             | Rust doesn 't bother with, especially around templates.
             | (Rust just has a more general macro feature instead. The
             | C++ folks are now on track to adding a clunky "metaclass"
             | feature which is a lot like Rust macros.)
        
               | pjmlp wrote:
               | Every language becomes a kitchen sink with enough time on
               | the market, even C, people really should learn about the
               | standard and the myriad of compiler extensions, K&R C was
               | almost 60 years ago.
               | 
               | C++ already has almost Rust macros, with a mix of compile
               | time execution, concepts and traits, without requiring
               | another mini-language, or an external crate (syn).
        
               | bmacho wrote:
               | > Every language becomes a kitchen sink with enough time
               | on the market,
               | 
               | Sometimes they remove stuff, and then everything written
               | before a specific date stop working.
        
             | tialaramex wrote:
             | > Go is not a C or Python replacement.
             | 
             | Google stopped writing new Python, because they found that
             | the same engineers would produce software with similar
             | defect rates, at a similar price and in similar time, with
             | Go, but it would have markedly better performance, so, no
             | more Python.
             | 
             | Go manages to have a nice sharp start, which means there
             | are going to be a bunch of cases where you didn't need all
             | the perf from C, but you did need a prompt start, so, Java
             | was not an option but Go is fine.
             | 
             | In my own practice, Rust entirely replaces C, which has
             | previously been my preferred language for many use cases.
        
             | xedrac wrote:
             | > Moving from C++ to Rust is a sideways move.
             | 
             | In what sense? Features or complexity? From a
             | productivity/correctness perspective, Rust is a huge step
             | up over C++.
        
               | pjmlp wrote:
               | While I agree, that isn't much the case for those using
               | static analysis, and hardened runtimes, which provide
               | much of the same safety improvements, granted without
               | lifetimes tracking.
               | 
               | Use more xcode, Clion, Visual Studio, C++ Builder, and
               | less vi and Emacs for C and C++.
               | 
               | Not everyone has the RIIR luxury for what we do.
        
               | xedrac wrote:
               | Those things certainly help, but as someone who actively
               | maintains a lot of C++, I'll stand by my claim that even
               | with those added tools, Rust is a very large upgrade in
               | both productivity and correctness. I'm not claiming all
               | C++ should be RIIR. But you won't find me starting any
               | new projects in C++, unless compelled to do so.
        
               | pjmlp wrote:
               | It is, provided there are crates available for what the
               | assignment is supposed to be.
               | 
               | However C++ folks aren't standing still, and anyone
               | pointing out to cargo, and not using conan/vcpkg,
               | alongside a C++ aware IDE, is doing themselves a
               | disservice, better be 85% there than none at all.
        
             | pjmlp wrote:
             | Go has plenty of bad design decisions, but not being a
             | safer C isn't one of them.
             | 
             | TinyGo and TamaGo folks enjoy writing their bare metal
             | applications on embedded and firmware.
        
           | superlopuh wrote:
           | My experience with Zig is that it's also a plausible
           | replacement for C++
        
             | fuzztester wrote:
             | explanation needed, bro.
             | 
             | nerdy langnoob or noobie langnerd here. not sure which is
             | which, cuz my parsing skills are nearly zilch. ;)
        
               | infamouscow wrote:
               | C programmers have long suffered the cumbersome ritual of
               | struct manipulation--resorting to C++ merely to dress up
               | structs as classes.
               | 
               | Zig shatters that with comptime and the 'type' type.
        
               | chongli wrote:
               | Zig's comptime feature gives a lot of the power of C++
               | templates. This makes it easier to implement a lot of
               | libraries which are just a pain to do in plain C. Even
               | seemingly simple things like a generic vector are
               | annoying to do in C, unless you abandon type safety and
               | just start passing pointers to void.
               | 
               | I believe Zig even has some libraries for doing more
               | exotic things easily, such as converting between an array
               | of structs and a struct of arrays (and back).
        
               | fuzztester wrote:
               | >Zig's comptime feature gives a lot of the power of C++
               | templates. This makes it easier to implement a lot of
               | libraries which are just a pain to do in plain C. Even
               | seemingly simple things like a generic vector are
               | annoying to do in C, unless you abandon type safety and
               | just start passing pointers to void.
               | 
               | I get it, thanks. in C you have to cast everything to
               | (void *) to do things like a generic vector.
               | 
               | >I believe Zig even has some libraries for doing more
               | exotic things easily, such as converting between an array
               | of structs and a struct of arrays (and back).
               | 
               | yes, iirc, there was a zig thread about this on hn
               | recently.
        
               | pjmlp wrote:
               | Depends on which C++ version you're talking about.
        
           | FpUser wrote:
           | >"but Rust is actually a replacement for C++. "
           | 
           | I would disagree. C++ provides way more features than Rust
           | and to me Rust feels way more constrained comparatively.
        
             | tialaramex wrote:
             | Sure, in the sense that in C++ they've got the Head Of
             | Vecna: https://rpgmuseum.fandom.com/wiki/The_Head_of_Vecna
             | 
             | Many of my favourite Rust features aren't in C++. For
             | example they don't have real Sum types, they don't have the
             | correct move semantic, they are statement oriented rather
             | than expression oriented and their language lacks decent
             | built-in tooling.
             | 
             | But also, some of the things C++ does have are just bad and
             | won't get fixed/ removed because they're popular. And
             | there's no sign of it slowing down.
             | 
             | I think that _in practice_ you should use Rust in most
             | places that C++ is used today, while some of the remainder
             | should be WUFFS, or something entirely different.
        
               | FpUser wrote:
               | >"I think that in practice you should use Rust"
               | 
               | I am doing fine. Thank you. Also I am not a language
               | warrior. I do have my preferences but use many since I am
               | an independent and work with many clients.
        
               | pjmlp wrote:
               | The biggest issue for me, is that Rust isn't used where I
               | care about, mainstream language runtimes, compiler
               | toolchains, and GPU ecosystem standards.
               | 
               | No one from them would accept a patch in Rust instead of
               | C or C++.
               | 
               | Yes I know about Deno, but even them haven't rewriten V8,
               | and wgpu or Rust CUDA aren't the same as what Khronos,
               | NVidia, AMD, Microsoft put out in C++.
        
           | krona wrote:
           | > Rust is actually a replacement for C++
           | 
           | Last I checked, rust touted itself as a _systems_ programming
           | language, which C++ kinda is but mostly isn 't (many C++
           | features just aren't appropriate or are poorly suited for
           | systems programming).
           | 
           | I would never choose Rust over C++ for scientific
           | programming, because Rust metaprogramming features are so
           | poor.
           | 
           | However I'd probably choose Rust over C in many areas where C
           | is best suited.
           | 
           | So to me the venn diagram of utility shows Rust to overlap
           | with C far more than C++.
        
         | smartmic wrote:
         | From what you describe, you might also like Odin.
        
           | zoogeny wrote:
           | Interestingly enough, it is one of the only "talked about"
           | languages I have almost no experience with. Even Roc I've
           | watched a few YouTube videos on. I've only really seen Odin
           | mentioned on X, not even a HN post.
           | 
           | I suppose there is also Jai in a similar space as well,
           | although I'm not a devotee to Jonathan Blow and I don't share
           | much of the excitement his followers seem to have.
           | 
           | I do feel Zig has the current trend moving in its favor, with
           | projects like Ghostty and Bun gaining prominence. I think
           | Odin would need something like that to really capture
           | attention.
        
             | dismalaf wrote:
             | Odin has commercial applications, basically all the JangaFX
             | apps... But yeah, it's missing a killer open source app.
             | Positive is it has a decent amount of batteries included.
        
             | smartmic wrote:
             | > I've only really seen Odin mentioned on X, not even a HN
             | post.
             | 
             | But there are some: https://hn.algolia.com/?q=Odin
        
             | johnisgood wrote:
             | I'm not a devotee to the creator of Odin. Odin may be fine,
             | but I'm hesitant when it comes to contributing to it. Welp.
             | Life goes on.
        
         | christophilus wrote:
         | I've played with Hare, Zig, and Odin. Odin is my favorite. It's
         | a fair bit faster to compile (similar to Hare), and has the
         | nicest syntax (subjectively speaking). I wish it would get more
         | traction. Looking forward to trying Jai if it ever makes it to
         | GA.
        
           | wolfspaw wrote:
           | Odin is the best (followed by Zig)
           | 
           | Odin has the best approach for "standard library" by
           | blessing/vendoring immensely useful libraries
           | 
           | Odin also has the best approach for Vector Math with native
           | Vector and Matrix types
        
             | tialaramex wrote:
             | The swizzling is pretty cool, rather special purpose but it
             | makes sense that Ginger Bill wanted this and it's Ginger
             | Bill's language.
             | 
             | Odin's "standard library" stuff is very silly, it still
             | feels like we were just copy-pasted the lead developer's
             | "useful stuff" directory. Bill doesn't feel there's a value
             | to actual standard libraries, so instead here's...
             | whatever. He insists that's not what's going on here, but
             | that doesn't change how it feels.
        
         | LAC-Tech wrote:
         | I don't say the "lower language wars" as being between zig and
         | rust. I see it as being between old and new. And I'm on team
         | new.
        
       | gregwebs wrote:
       | 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 wrote:
         | 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.)
        
           | eximius wrote:
           | But were any _language_ decisions discarded due to compile
           | time concerns? I don't think anyone would claim the folks
           | working on the rust compiler don't care.
           | 
           | On that note, thank you for your part! I sure enjoy your
           | work! :)
        
             | LegionMammal978 wrote:
             | Since at least 2018, there's been a planned upgrade to the
             | borrow checker to permit certain patterns that it currently
             | rejects [0]. Also since 2018, there's been an
             | implementation of the new version (called Polonius) that
             | can be enabled with an unstable compiler flag [1].
             | 
             | But now it's 2025, and the new version still hasn't been
             | enabled on stable Rust, since the Polonius implementation
             | is seen as far too slow for larger programs. (I'm not
             | exactly sure how horrible it really is, I haven't looked at
             | the numbers.) A big goal of the types team since last year
             | has been to reimplement a faster version within rustc [2].
             | 
             | I'd count this as a language feature (albeit a relatively
             | minor one) that's been greatly deferred in favor of shorter
             | compile times.
             | 
             | [0] https://blog.rust-lang.org/inside-
             | rust/2023/10/06/polonius-u...
             | 
             | [1] https://github.com/rust-lang/rust/pull/51133
             | 
             | [2] https://rust-lang.github.io/rust-project-
             | goals/2024h2/Poloni...
        
               | gregwebs wrote:
               | That's useful information and we are all glad that
               | performance regressions aren't allowed now and there is
               | work to make things faster. But that seems to be
               | implementations of existing language design decisions
               | rather than making language design decisions for the sake
               | of compile times.
        
           | o11c wrote:
           | Yet, the whole crate model giving up on ABI stability as a
           | goal hurts a lot, both for performance and for sanity.
           | 
           | Why aren't people designing modern languages to make it
           | _easier_ to keep a stable ABI, rather than giving up
           | entirely?
        
             | pcwalton wrote:
             | ABI stability is one of those things that seems obvious
             | ("sane"), until you try to implement ABI-stable unboxed
             | generics and discover that the amount of complexity you
             | incur, as well as the performance tax, is absurd. The code
             | bloat with the resulting "intensional type analysis"
             | actually makes the compile time worse (and the runtime far
             | worse) than just specializing generics in many cases.
        
               | zozbot234 wrote:
               | The Swift folks seem to manage just fine.
        
               | pcwalton wrote:
               | The amount of complexity that Swift has to deal with in
               | order to make ABI stability work is exactly what I'm
               | talking about. It's astronomical. Furthermore, it's only
               | partial: there are some generics in which they couldn't
               | afford the price of ABI stability, so they're marked
               | inline and aren't ABI stable.
        
               | kldx wrote:
               | I like Aria's writing about this
               | https://faultlore.com/blah/swift-abi/.
        
               | throwaway17_17 wrote:
               | In this case (i.e. Rust specifically) what do unboxed
               | generics mean. Without actually knowing Rust I don't
               | think I can analogize to either type theory or another
               | language. I assume if I can figure out what they are I
               | infer why they are difficult to compile.
        
               | zozbot234 wrote:
               | It means ABI-stable interfaces (i.e. interfaces between
               | separately-compiled "crates"/libraries, including dylibs
               | and shared objects) can involve arbitrarily complex types
               | with possibly nested generics, and these are implemented
               | behind a _single_ pointer dereference at most. This
               | requires something a lot like dyn trait object vtables in
               | Rust ( "witness tables") except quite a bit more complex.
        
           | bhansconnect wrote:
           | Thank you for your work! Rust is still a great language.
           | 
           | I think a significant portion of our pain with rust compile
           | times is self inflicted due to the natural growth of our
           | crate organization and stages.
           | 
           | I still think the rewrite in zig is the right choice for us
           | for various reasons, but I think at least a chunk of our
           | compile times issues are self inflicted (though this happens
           | to any software project that grows organically and is 300k
           | LOC)
        
           | kettlecorn wrote:
           | The Rust ecosystem has long downplayed the importance of
           | compile times.
           | 
           | Many foundational crates, serde for example, contribute much
           | more to compile times than they need to.
           | 
           | I spent a long time reinventing many foundational rust crates
           | for my game engine, and I proved its possible to attain
           | similar features in a fraction of the compile time, but it's
           | a losing battle to forgo most of the ecosystem.
        
       | betimsl wrote:
       | I think Go would have been a better choice.
        
         | anacrolix wrote:
         | absolutely not. both because it's awful for implementing
         | parsers, but also it introduces lots of extra hoops for
         | interop.
         | 
         | its build system is also terrible for targeting lots of varying
         | platforms and feature sets.
         | 
         | it has a custom IR that isn't helpful interacting with other
         | systems.
         | 
         | its runtime is really nice but it's a black box and not
         | suitable for interop.
        
       | wiz21c wrote:
       | I use rust a lot but, Roc is right: compilation times are not
       | proportional to the safety you gain. At least in my project.
        
         | Gibbon1 wrote:
         | I had an issue where the corporate spyware thought my cross
         | compiler was potential malware and running scans on every file
         | access. My compile times went from a few seconds to 2 minutes.
         | And my codebase has a dozen targets. Where building, fixing,
         | running tests, checking in would take half and hour it now took
         | the whole afternoon.
         | 
         | I think I'd rather stick with C and run static analysis tools
         | on my code when generating release candidates than have to deal
         | with that.
        
           | airstrike wrote:
           | That's hardly the language's fault
        
       | stevage wrote:
       | If author is reading this, maybe worth a paragraph saying why
       | you're not rewriting in Roc.
        
         | anacrolix wrote:
         | because that's hard. also it's one choice I respect them for
         | not making: don't self host until you have actual users and
         | momentum (unless you want to to prove a point). if Roc intends
         | to have industry usage, keeping it in another language for now
         | is a good move.
        
           | bhansconnect wrote:
           | Roc never plans to self host. We want roc the compiler in the
           | long term to be as nice as possible for end users. A big part
           | of that is as fast as possible. While roc can be fast, it
           | can't compete with all the techniques that can be done in
           | rust/zig/c/c++. It fundamentally is a higher level language
           | to increase developer joy and reduce bugs. So it isn't the
           | right tool when you are trying to reach the limits of
           | hardware like this.
        
         | teo_zero wrote:
         | Like this one?
         | 
         | > Roc's compiler has always been written in Rust, and we do not
         | plan to self-host. We have a FAQ entry explaining why, and none
         | of our reasoning has changed on that subject.
        
         | bhansconnect wrote:
         | https://www.roc-lang.org/faq.html#self-hosted-compiler
        
       | mr_00ff00 wrote:
       | I remember reading the HN thread when Fish rewrote to Rust. A big
       | reason because "they wanted to stay current" so they rewrote from
       | C++ to Rust.
       | 
       | Someone made a joke comment how in a few years there would be
       | tons of HN threads about rewriting Rust to Zig.
        
       | sweeter wrote:
       | Yay for Zig! I'm a big Zig fan. It's seemless interop with C
       | makes it super fun. I really enjoy writing code in a C-style way.
       | Its still got some rough edges, but its definitely super fun and
       | enjoyable to write imo.
        
       | marxisttemp wrote:
       | I've been reading a lot about comptime in Zig and it's really
       | cool, it unifies and simplifies a lot of metaprogramming concepts
       | that normally end up being the ugliest and clunkiest parts of
       | most languages.
       | 
       | I've been immersed in Swift for a couple years after working as a
       | Go programmer, and I find myself pining for a language that's
       | more expressive than the latter and more concise than the former.
        
       | nialv7 wrote:
       | Whenever I see <language A> rewrites its compiler in <language
       | B>, and A != B, I lose a bit of interest in language A.
        
         | Hasnep wrote:
         | Why? Roc has good reasons for not self hosting the compiler.
        
           | nialv7 wrote:
           | Well their main reason is a compiler written in Roc won't be
           | performant. (And their tag line is "Roc: A _fast_, friendly,
           | functional language.")
           | 
           | So yeah, I am not interested. Plus I feel in general not
           | dogfooding your own language is a bad sign.
        
             | Hasnep wrote:
             | That excludes all languages that want to write the compiler
             | in a lower level language than the target language itself.
             | You can easily imagine a high level language with a fast
             | compiler written in C where if you rewrote the compiler to
             | be self hosted the performance would drop 10-100x.
             | 
             | Dog-fooding is important, but it can be done outside of
             | compiler development. If the only code the compiler team
             | writes is the compiler, they end up designing a language
             | that's great for implementing compilers at the expense of
             | other use cases.
        
       | petabyt wrote:
       | Fast compile times in Zig? Last time I tried it was super slow.
       | Has anything changed in recent years?
        
         | pverghese wrote:
         | Compared to Rust its blazingly fast. Compared to Go compilation
         | its slower.
        
           | metaltyphoon wrote:
           | Non it's not. I known its not a benchmark but just try a zig
           | init and build their hello world. It takes significantly
           | longer
        
             | sweeter wrote:
             | ```sh
             | 
             | sweet@nadeko ~ $ mkcd test
             | 
             | sweet@nadeko ~/test $ zig init
             | 
             | info: created build.zig
             | 
             | info: created build.zig.zon
             | 
             | info: created src/main.zig
             | 
             | info: created src/root.zig
             | 
             | info: see `zig build --help` for a menu of options
             | 
             | sweet@nadeko ~/test $ time zig build
             | 
             | zig build 5.08s user 0.58s system 119% cpu 4.745 total
             | 
             | # cached
             | 
             | sweet@nadeko ~/test $ time zig build
             | 
             | zig build 0.01s user 0.03s system 132% cpu 0.026 total
             | 
             | # after rewriting the main function to call a function that
             | takes a pointer to another function
             | 
             | sweet@nadeko ~/test $ time zig build
             | 
             | zig build 0.02s user 0.03s system 136% cpu 0.032 total
             | 
             | ```
        
             | baazaa wrote:
             | think this has something to do with zig building part of
             | the std which other languages ship as binaries. incremental
             | compilation will remove this small overhead.
        
             | jedisct1 wrote:
             | The first time you run the toolchain for a given target, it
             | compiles stuff that is then stored in a global cache.
        
         | rererereferred wrote:
         | Their x86 backend seems to be more complete, bypassing LLVM and
         | allowing for fast debug builds.
        
           | zozbot234 wrote:
           | Rust has a Cranelift-based backend that you can use for that.
        
             | bhansconnect wrote:
             | It sadly helps a lot less than you would hope. A true dev
             | backend can be many times faster than llvm to compile code.
             | Crane lift is more like a 1.5x or 2x. Not to mention a lot
             | of time is spent in the rust frontend.
        
         | modernerd wrote:
         | Last time I tried it was missing both speed and incremental
         | compilation. That still looks to be the case due to no linker
         | support.
         | 
         | https://github.com/ziglang/zig/issues/21165
        
         | sweeter wrote:
         | Its honestly pretty dang good now. I can bootstrap Zig from C
         | in about 3-5 minutes, and then use the self-hosted stage3
         | compiler to compile Zig very quickly (under 1 minute iirc) Once
         | the cache kicks in, its even faster. I guess my overall gauge
         | on this is the impression I get. Zig build times never annoy me
         | and I never think about it... especially compared to clang, gcc
         | and Rust.
        
       | kreelman wrote:
       | The ROC webpage talks about ROC doing web servers via Rust
       | libs...                  Behind the scenes, it uses Rust's high-
       | performance hyper and tokio libraries to         execute your Roc
       | function on incoming requests.
       | 
       | Will these be replaced with Zig networking libs?
        
         | isaacvando wrote:
         | Not necessarily! Each Roc app runs on a particular platform
         | which is built in a host language for a specific domain. That
         | host language could be Rust, Zig, C, C++, Go, Swift, etc. It's
         | possible the basic-webserver platform will be rewritten to Zig
         | but it doesn't need to be.
        
       | einpoklum wrote:
       | It is interesting to note an intentional choice to go from a
       | "safe" language to an "unsafe" language for a program whose use
       | is not without security implications (even if it's not network-
       | facing).
        
       | 3836293648 wrote:
       | Maybe I need to give it another shot, but Zig was a terribly
       | unpleasant language last I tried to use it.
       | 
       | Their motivation seems to justify the decision, but I'm pretty
       | sure this will scare away potential contributors. I've been
       | following Roc personally, and probably will continue to do so,
       | but this definitely has killed a lot of interest for me.
        
       | 5- wrote:
       | > _Zig came up with a way around this: compile directly to LLVM
       | bitcode (LLVM has strong backwards-compatibility on its bitcode
       | but not on its public-facing API) and then upgrades become
       | trivial because we can keep our existing code generation the
       | same._
       | 
       | i'm glad that zig helps offset what i find a rather worrying
       | trend -- replacing protocols with libraries (and as a consequence
       | designing new underlying protocols in view of their only being
       | used through the vendor library).
       | 
       | protocols are traditionally designed to facilitate an independent
       | implementation; in fact, many standards ratification processes
       | require several independent implementations as a prerequisite.
       | 
       | libraries (or worse, frameworks) intermingle the actual api with
       | their own design, and necessitate a single implementation.
       | 
       | just the other day i wanted to display a notification a linux
       | desktop where it wasn't convenient to depend on a library (it was
       | a game, so not a traditional application expected to have many
       | dependencies). the protocol (there is one, wrapped by the
       | library) is very unpleasant, but i got it working out of spite.
       | 
       | and of course, when there is a perfectly nice protocol available
       | (llvm ir, in either the bitcode or text representation) why not
       | choose it? at least on unix, where starting processes and
       | interprocess communication is cheap. (and as an added bonus, you
       | won't crash when llvm does.)
        
         | steveklabnik wrote:
         | LLVM IR is not stable, which is a prerequisite for a good
         | protocol.
        
       | poulpy123 wrote:
       | I'm not educated enough to give an opinion but I find it weird to
       | rewrite in a language that is so new
        
       ___________________________________________________________________
       (page generated 2025-02-05 23:02 UTC)