> 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…
Thoughts on Go vs. Rust vs. Zig
161–170 of 599 posts
Re: Thoughts on Go vs. Rust vs. Zig
#162But 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
#163Earlier 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?
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
#164I 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++
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…
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
#166I 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?
Re: Thoughts on Go vs. Rust vs. Zig
#167> 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.
Re: Thoughts on Go vs. Rust vs. Zig
#168Earlier 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.
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
#169Earlier 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.
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
#170Earlier 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…
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?