Live data from Hacker News

Thoughts on Go vs. Rust vs. Zig

sinclairtarget.com

161–170 of 599 posts

Re: Thoughts on Go vs. Rust vs. Zig

#161
post #60

> In Go, a slice is a fat pointer to a contiguous sequence in memory, but a slice can also grow, meaning that it subsumes the functionality of Rust’s Vec type and Zig’s ArrayList. Well, not exactly. This is actually a great example of the Go philosophy of being "simple" while not being "easy". A Vec has identity; the memory underlying a Go slice does not. When you call append(), a new slice is returned that may or ma…

> Go programmer attitude is "do what I said, and trust that I read the library docs before I said it". I agree and think Go gets unjustly blamed for some things: most of the foot guns people say Go has are clearly laid out in the spec/documentation. Are these surprising behaviors or did you just not read? Getting a compiler and just typing away is not a great way of going about learning things if that compiler is not…

It's not unjust to blame the tool if it behaves contrary to well established expectation, even if that's documented - it's just poor ergonomics then.

Re: Thoughts on Go vs. Rust vs. Zig

#162
> I’m not the first person to pick on this particular Github comment, but it perfectly illustrates the conceptual density of Rust:

But you only need about 5% of the concepts in that comment to be productive in Rust. I don't think I've ever needed to know about #[fundamental] in about 12 years or so of Rust…

> In both Go and Rust, allocating an object on the heap is as easy as returning a pointer to a struct from a function. The allocation is implicit. In Zig, you allocate every byte yourself, explicitly. […] you have to call alloc() on a specific kind of allocator,

> In Go and Rust and so many other languages, you tend to allocate little bits of memory at a time for each object in your object graph. Your program has thousands of little hidden malloc()s and free()s, and therefore thousands of different lifetimes.

Rust can also do arena allocations, and there is an allocator concept in Rust, too. There's just a default allocator, too.

And usually a heap allocation is explicit, such as with Box::new, but that of course might be wrapped behind some other type or function. (E.g., String, Vec both alloc, too.)

> In Rust, creating a mutable global variable is so hard that there are long forum discussions on how to do it.

The linked thread is specifically about creating a specific kind of mutable global, and has extra, special requirements unique to the thread. The stock "I need a global" for what I'd call a "default situation" can be as "simple" as,

  static FOO: Mutex = Mutex::new(…);
Since mutable globals are inherently memory unsafe, you need the mutex.

(Obviously, there's usually an XY problem in such questions, too, when someone wants a global…)

To the safety stuff, I'd add that Rust not only champions memory safety, but the type system is such that I can use it to add safety guarantees to the code I write. E.g., String can guarantee that it always represents a Unicode string, and it doesn't really need special support from the language to do that.

Re: Thoughts on Go vs. Rust vs. Zig

#163
post #43

Earlier quoted context omitted.

These are extremely trivial, to the point that I don’t really know what you’re complaining about. What would expect or prefer?

it's not about triviality, but why not use what is generally accepted already, why did zig decide to be different?

What is "generally accepted" though?

If you mean C-style declarations, the fact that tools such as https://linux.die.net/man/1/cdecl even exist to begin with shows what's wrong with it.

Re: Thoughts on Go vs. Rust vs. Zig

#164
post #49

I could never get into zig purely because of the syntax and I know I am not alone, can someone explain the odd choices that were taken when creating zig? the most odd one probably being 'const expected = [_]u32{ 123, 67, 89, 99 };' and the 2nd most being the word 'try' instead of just ? the 3rd one would be the imports and `try std.fs.File.stdout().writeAll("hello world!\n");` is not really convincing either for a ba…

I will never understand people bashing other languages for their syntax and readability and then saying that they prefer Rust. Async Rust is the ugliest and least readable language I've ever seen and I've done a lot of heavily templated C++

Concur, but non-async rust is a different matter!

Re: Thoughts on Go vs. Rust vs. Zig

#165

> Other features common in modern languages, like tagged unions or syntactic sugar for error-handling, have not been added to Go. > It seems the Go development team has a high bar for adding features to the language. The end result is a language that forces you to write a lot of boilerplate code to implement logic that could be more succinctly expressed in another language. Being able to implement logic more succinct…

That isn't apples to apples.

In Rust I could have done (assuming `anyhow::Error` or `Box` return types, which are very typical):

    let mut file = File::create("foo.txt")
        .map_err(|e| format!("failed to create file: {e}")?;
Rust having the subtle benefit here of guaranteeing at compile type that the parameter to the string is not omitted.

In Go I could have done (and is just as typical to do):

    f, err := os.Create("filename.txt")
    if err != nil {
        return err
    }
So Go no more forces you to do that than Rust does, and both can do the same thing.

Re: Thoughts on Go vs. Rust vs. Zig

#166

I love this take - partly because I agree with it - but mostly because I think that this is the right way to compare PLs (and to present the results). It is honest in the way it ascribes strengths and weaknesses, helping to guide, refine, justify the choice of language outside of job pressures. I am sad that it does not mention Raku ( https://raku.org ) ... because in my mind there is a kind of continuum: C - Zig - C…

what's WL?

Wolfram Language?

Re: Thoughts on Go vs. Rust vs. Zig

#167
post #51

> Other features common in modern languages, like tagged unions or syntactic sugar for error-handling, have not been added to Go. > It seems the Go development team has a high bar for adding features to the language. The end result is a language that forces you to write a lot of boilerplate code to implement logic that could be more succinctly expressed in another language. Being able to implement logic more succinct…

I also prefer Rust's enums and match statements for error handling, but think that their general-case "ergonomic" error handling patterns --- the "?" thing in particular --- actually make things worse. I was glad when Go killed the trial balloon for a similar error handling shorthand. The good Rust error handling is actually wordier than Go's.

Nah, you just need to use `map_err` or apply a '.context' which I think anyhow can do (and my crate, `uni_error` certainly can otherwise).

Re: Thoughts on Go vs. Rust vs. Zig

#168
post #104
post #49

Earlier quoted context omitted.

I will never understand people bashing other languages for their syntax and readability and then saying that they prefer Rust. Async Rust is the ugliest and least readable language I've ever seen and I've done a lot of heavily templated C++

> Async Rust is the ugliest and least readable language I've ever seen and I've done a lot of heavily templated C++ No, this is a wild claim that shows you've either never written async Rust or never written heavily templated C++. Feel free to give code examples if you want to suggest otherwise.

Every language i am not deeply familiar with is disgusting.

But for real the ratings for me stem from how much arcane symbology i must newly memorize. I found rust to be up there but digestible. The thought of c++ makes me want to puke but not over the syntax.

Re: Thoughts on Go vs. Rust vs. Zig

#169

Earlier quoted context omitted.

I imagine people who care about this sort of thing are happy to disable overcommit, and/or run Zig on embedded or specialized systems where it doesn't exist.

There are far more people running/writing Zig on/for systems with overcommit than not. Most of the hype around Zig come from people not in the embedded world.

If we can produce a substantial volume of software that can cope with allocation failures then the idea of using something than overcommit as the default becomes feasible.

It's not a stretch to imagine that a different namespace might want different semantics e.g. to allow a container to opt out of overcommit.

It is hard to justify the effort required to enable this unless it'll be useful for more than a tiny handful of users who can otherwise afford to run off an in-house fork.

Re: Thoughts on Go vs. Rust vs. Zig

#170
post #153

Earlier quoted context omitted.

Python's f = open('foo.txt', 'w') is even more succinct, and the exception thrown on failure will not only contain the reason, but the filename and the whole backtrace to the line where the error occurred.

But no context, so in the real world you need to write: try: f = open('foo.txt', 'w') except Exception as e: raise NecessaryContext("important information") from e Else your callers are in for a nightmare of a time trying to figure out why an exception was thrown and what to do with it. Worse, you risk leaking implementation details that the caller comes to depend on which will also make your own life miserable in th…

How is a stack trace with line numbers and a message for the exception it self not enough information for why an exception was thrown?

The exceptions from something like open are always pretty clear. Like, the files not found, and here is the exact line of code and the entire call stack. what else do you want to know to debug?

Post reply on HN