Earlier quoted context omitted.
The only thing I really found weird syntactically when learning it was the single quote for lifetimes because it looks like it’s an unmatched character literal. Other than that it’s a pretty normal curly-braces language, & comes from C++, generic constraints look like plenty of other languages. Of course the borrow checker and when you use lifetimes can be complex to learn, especially if you’re coming from GC-land, j…
Agreed. In practice Rust feels very much like a rationalized C++ in which 30 years of cruft have been shrugged off. The core concepts have been reduced to a minimum and reinforced. The compiler error messages are wildly better. And the tooling is helpful and starts with opinionated defaults. Which all leads to the knock-on effect of the library ecosystem feeling much more modular, interoperable, and useful.
Thoughts on Go vs. Rust vs. Zig
511–520 of 599 posts
Re: Thoughts on Go vs. Rust vs. Zig
#512Earlier quoted context omitted.
I tried to get an LLM to write a Raku chapter in the same vein - naah. Had to write it myself: Raku Raku stands out as a fast way to working code, with a permissive compiler that allows wide expression. Its an expressive, general-purpose language with a wide set of built-in tools. Features like multi-dispatch, roles, gradual typing, lazy evaluation, and a strong regex and grammar system are part of its core design. T…
I see that my Raku chapter was downvoted a couple of times. Well OK, I am an unashamed shill for such a fantastic and yet despised language. Don’t knock til you try it. Some comments below on “I want a Go, but with more powerful OO” - well Raku adheres to the Smalltalk philosophy… everything is an object, and it has all the OO richness (rope) of C++ with multiple inheritance, role composition, parametric roles, MOP,…
That said, agree Raku is cool. A big disadvantage though it has (or had?), more than the sigils-everywhere syntax & small ecosystem, is performance. It's slower than pre-JIT Python. Go also natively-compiles to self-contained binaries, which some people appreciate. (And there're those that prefer Go's simplicity and don't want very high expressiveness other than specific features.)
Re: Thoughts on Go vs. Rust vs. Zig
#513Earlier quoted context omitted.
I see that my Raku chapter was downvoted a couple of times. Well OK, I am an unashamed shill for such a fantastic and yet despised language. Don’t knock til you try it. Some comments below on “I want a Go, but with more powerful OO” - well Raku adheres to the Smalltalk philosophy… everything is an object, and it has all the OO richness (rope) of C++ with multiple inheritance, role composition, parametric roles, MOP,…
Probably was downvoted because it seem to copy-paste/derive-off an LLM output since, even if you say you wrote it yourself, some distinct LLM grammar/style characteristics appear. (Could just be you picked them as habit after use of such tools.) It doesn't appear to in same vein either. The submitted article's descriptions are, for each language, {philosophy} & {specific design examples}. Yours is mainly on {design}.…
Re: Thoughts on Go vs. Rust vs. Zig
#514Earlier quoted context omitted.
Writing "append(s, ...)" instead of "s = append(s, ...)" results in a compiler error because it is an unused expression. I'm not sure how a newbie could make this mistake since that code doesn't compile.
Indeed the usual error is b := append(a, …)
Re: Thoughts on Go vs. Rust vs. Zig
#515Earlier quoted context omitted.
With the same difficulties as Java.
But it's improving fast. They even made the new file-based apps target Native AOT by default ( https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotn... ).
Re: Thoughts on Go vs. Rust vs. Zig
#516Earlier quoted context omitted.
> languages where "trivial" things "just require" rapidly become "not so trivial" in the aggregate Sure. And in C and Zig, it's "trivial" to make a global mutable variable, it "just requires" you to flawlessly uphold memory access invariants manually across all possible concurrent states of your program. Stop beating around the bush. Rust is just easier than nearly any other language for writing concurrent programs,…
Rust is a 99% solution to a 1% problem.
And the situations where you really need a "systems programming" environment have been really at best a wash with Rust. It's mostly replacing boring middleware (c.f. the linked article). Where are the rustacean routing engines and database backends and codecs and kernels? Not in deployment anywhere, not yet. C still rules that world, even for new features.
[1] Well, everything big enough to need a typesafe high performance platform. The real "everything", to first approximation, should be in python.
Re: Thoughts on Go vs. Rust vs. Zig
#517Earlier quoted context omitted.
> If your execution environment is simple enough they can be quite useful and effective Saud by many an engineer whose code was running in systems that were in fact not that simple! What is irksome is that globals are actually just kinda straight worse. Like the code that doesn't use a singleton and simply passes a god damn pointer turns out to be the simpler and easier thing to do. > What types of code are you worki…
> All I want in life is a pure C API. It is simple and elegant and delightful and you can wrap it to run in any programming environment in existence. Sure thing boss, here's that header file populated exclusively by preprocessor macros that you asked for.
Re: Thoughts on Go vs. Rust vs. Zig
#518Earlier quoted context omitted.
Indeed the usual error is b := append(a, …)
How is that an error if b is properly referenced? It’s perhaps a waste of memory but not wrong
a := make([]int, 0, 5)
a = append(a, 0, 0)
b := append(a, 1)
a = append(a, 0)
fmt.Println(b)
prints [0 0 0]
because the following happens: a := make([]int, 0, 5)
// a = [() _ _ _ _ _]
// a has length 0 but the backing buffer has capacity 5, between the parens is the section of the buffer that's currently part of a, between brackets is the total buffer
a = append(a, 0, 0)
// a = [(0 0) _ _ _]
// a now has length 2, with the first two locations of the backing buffer zeroed
b := append(a, 1)
// b = [(0 0 1) _ _]
// b has length 3, because while it's a different slice it shares a backing buffer with a, thus while a does not see the 1 it is part of its backing buffer:
// a = [(0 0) 1 _ _]
a = append(a, 0)
// append works off of the length, so now it expands `a` and writes at the new location in the backing buffer
// a = [(0 0 0) _ _]
// since b still shares a backing buffer...
// b = [(0 0 0) _ _]Re: Thoughts on Go vs. Rust vs. Zig
#519Re UB: > The idea seems to be that you can run your program enough times in the checked release modes to have reasonable confidence that there will be no illegal behavior in the unchecked build of your program. That seems like a highly pragmatic design to me. This is only pragmatic if you ignore the real world experience of sanitizers which attempt to do the same thing and failing to prevent memory safety and UB issu…
Can you provide the source of "(eg Android definitely has sanitizers running on every commit and yet it wasn’t until they switched to Rust that exploits started disappearing)"?
https://security.googleblog.com/2025/11/rust-in-android-move...
Re: Thoughts on Go vs. Rust vs. Zig
#520Earlier quoted context omitted.
One of my favorite talks of all-time is the GDC talk on Overwatch's killcam system. This is the thing that when you die in a multiplayer shooter you get to see the last ~4 seconds of gameplay from the perspective of your killer. https://www.youtube.com/watch?v=A5KW5d15J7I The way Blizzard implemented this is super super clever. They created an entirely duplicate "replay world". When you die the server very quickly "b…
If we're getting philosophical, we can identify a hierarchy of globals: 1. Read-only (`const`s in Rust). These are fine, no objections. 2. Automatic-lazily-initialized write-once, read-only thereafter (`LazyLock` in Rust). These are also basically fine. 3. Manually-initialized write-once, read-only thereafter (`OnceLock` in Rust). These are also basically fine, but slightly more annoying because you need to be sure t…
2 and 3 are basically fine. Just so long as you don’t rely on initialization order. And don’t have meaningful cleanup. C++ initialization fiasco is great pain. Crash on shutdown bugs are soooo common with globals.
4 of have to think about.
And yes 5 is the evilness.