Live data from Hacker News

Assorted Thoughts on Zig and Rust

scattered-thoughts.net

61–70 of 307 posts

Re: Assorted Thoughts on Zig and Rust

#61
This is a really great writeup! I was using Rust as my main programming language from some months before 1.0 up until maybe early 2019. I have only written somewhere in between 100 and 1k lines of Zig, but generally feel that I agree with most of what's being brought up here.

Here's a mind dump:

> Zig manages to provide many of the same features with a single mechanism - compile-time execution of regular zig code. This comes will all kinds of pros and cons, but one large and important pro is that I already know how to write regular code so it's easy for me to just write down the thing that I want to happen.

This is a huge one for me, and I really don't understand why Rust didn't jump on this earlier. Using the programming language for configs, generics, macros, and anything else that you'd want at compile time just seems like such a huge win, instead of having weird preprocessors-like systems, some config file format with arbitrary limitations, and weird marcro-like systems that either have crazy syntax (like `macro_rules!` in Rust), or that are way too limiting (like `const` functions in Rust).

Jon Blows language seem to take a similar stance as Zig; let's see if it ever hits public beta.

> On the other hand, we can't type-check zig libraries which contain generics. We can only type-check specific uses of those libraries.

This is definitely a concern I have about this "C++-like generics". My experience with C++ suggests that this is bad, but on the other hand, improving even just error messages would be such a day-night improvement, that I don't really trust my judgement on this one.

> Both languages will insert implicit casts between primitive types whenever it is safe to do so, and require explicit casts otherwise.

Is this really true? I seem to recall having to have plenty of `as usize` in my code when using smaller integer types for indices, but maybe this has changed (or maybe I'm misreading what's being said here).

> In rust the Send/Sync traits flag types which are safe to move/share across threads. In the absence of unsafe code it should be impossible to cause data races.

This is probably Rust's main selling point, because as far as I can tell, no other mainstream language comes even close to getting static thread safe guarantees (up to your definition of mainstream). As time goes on, however, I'm getting less and less excited about this, because most of my programs are not multithreaded, and the very few times that I need multiple threads, there is often very obvious and small boundaries in between the threads. It's just not very interesting to me that I _could_ be writing programs with thousands of threads all jumping around without having to worry about data races, because I don't really worry about it in the first place. But still, I as a Rust programmer, have to pay the price for this option being available.

> Undefined behavior in rust is defined here. It's worth noting that breaking the aliasing rules in unsafe rust can cause undefined behavior but these rules are not yet well-defined.

I'm not sure what to say about this, except that it's surprising that there seem to be a lack of voices about this in the Rust community. How can anyone comfortably write `unsafe` code without knowing what the rules are? Especially when the compiler is so "good" at depending on the "rules"? I don't understand. I have pretty limited experience with unsafe, but I have written some, and was often confused about which bugs were my logic bugs and which were the compiler assuming I didn't break some rule I didn't know about. Combine this with a poor debugging story overall, and you have a pretty miserable experience programming.

Maybe this isn't a problem in practice, or maybe all people succesfully writing `unsafe` code for libraries are also `rustc` veterans?

> @import takes a path to a file and turns the whole file into a struct. So modules are just structs.

This is a very nice approach! I remember from earlier Rust that the module system was a real pain point for beginners, and can also remember really struggeling with it. Curiously though, I also remember looking back, not understanding why anything was confusing about it. This was also redone(?) at some point, and I think it's nicer now.

> In rust my code is littered with use Expr::* and I'm careful to avoid name collisions between different enums that I might want to import in the same functions. In zig I just use anonymous literals everywhere and don't worry about it.

I've always been bothered by Rust's inability to infer the `enum` type in a `match`; in other places Rust has no problems being automagick, and this is really very annoying to go around, either with `use Foo::*` before each match, or having it in file scope and hope for no collisions. Zig seems to take exactly the approach I'd go for.

> Re allocators

I think Zig's stand on explicit allocators is very good; I've seen enough bad code in other languages that allocates here and there for things that, very clearly, doesn't need to be there. Having the language be explicit about allocations makes it easier to stop and say "hey wait a minute, is this realy the way I'm supposed to do it?", but without having to jump through hoops if you _just_ want to allocate something somewhere (define a global allocator yourself). And, as a bonus, it's easier to handle the allocations of other peoples code.

> Zig has no syntax for closures.

I definitely need to write more Zig to find out whether this is a problem or not. I've written a lot of C++ lately, and while there _are_ closures available, I think I've only used them once. Maybe the reason for my comparatively heavy closure usage in Rust was that so many methods in the standard libray took closures that you're shephearded into making similar methods for your own types.

> Zig's error handling model is similar to rust's, but it's errors are an open union type rather than a regular union type like rust's.

I really think the error story is why I prefer Zig to Rust now. The giant error `enum` in Rust is definitely what I'd go with because it's simply not feasible to manually track which functions return what errors and making individual enums yourself, even though this is super easy for the compiler to do, like Zig shows.

Not to pick on anyone in particular, but sometimes it feels like many programmers think that a program only consist of the happy path and that errors are somehow rare and not worth dealing with properly. Both Rust and Zig are huge helps to combat this mindset, but I do think that Zig comes out ahead, simply by being less annoying to work with. Also, while some people might say that `Result` just being a part of `core` and not a magic special language thing is cool, I do appreciate Zig's usage of `?` since it's way less typing for something that happens _all_ the time.

> Zig's compilation is lazy. Only code which is actually reachable needs to typecheck. So if you run zig test --test-filter the_one_test_i_care_about_right_now then only the code used for that test needs to typecheck.

I didn't know this, but this is awesome!

> Zig has absurdly good support for cross-compiling.

I've never understood why cross-compiling isn't an out-of-the-box feature in all languages. Don't you basically just have to target a different instruction set? Well, and a different executable format. But still, compared to all of the other crazy things compilers are doing, this seems very straight forward in comparison.

> Zig has an experimental build system where the build graph is assembled by zig code.

See above. I really really really don't understand why all languages doesn't do this already.

> In rust, blocks are expressions.

This is something I really like about Rust and a pattern I've used a lot, where I'd say

    let some_thing = {
        let foo = ...
        let bar = foo.baz() + quiz();
        ...
        foo
    };

to avoid accidently using `bar` somewhere else. Granted, since Rust allows shadowing this isn't really a problem most of the time, but it's definitely something I miss when writing C++. Zigs version is somewhat verbose, but I'll manage.

> There is an in-progress incremental debug compiler for zig that aims for sub-second compile times for large projects. Based on progress so far, this is a plausible goal.

Andrew's work on binary patching executables is really cool. I hope we'll get to compile times this low, even for moderately sized projects.

> real 23m27.475s

This is just sad. Despite all the work the contributors to `rustc` are doing, it just seems that they are in a completely different league with respect to compile times than what I'd like. I hope the steady progess they're making will either make some jumps, or continue for a while :)

> Main points so far:

This is a great summary, and I think people reading it (or the whole post) will have a pretty good idea of where they stand re. the two languages.

Re: Assorted Thoughts on Zig and Rust

#62
post #49

I think this an argument like the following is not really meaningful: > Most of this difference is not related to lifetimes. Rust has patterns, traits, dyn, modules, declarative macros, procedural macros, derive, associated types, annotations, cfg, cargo features, turbofish, autoderefencing, deref coercion etc Nobody forces beginners to write macros. Beginners are only macros _users_. With time and experience, the ne…

This reminds me of the (by now) old saying that code is more often read than written - sure, you're not forced to write macros, but if you use macros (or more exotic features), you force the developers who read your code to become familiar with (possibly arcane) features that they maybe would have never used (or needed). That's why I think Go's approach to not try to be "everybody's darling" by implementing every con…

I think your words come from experience.

It's not about how effortless the code is to write, but the total lifecycle effort. This includes for example maintenance, security, extending and on-boarding new team members.

Re: Assorted Thoughts on Zig and Rust

#63

I enjoy Rust and have been writing it for quite some time. However, I feel like server side languages still have a long way to go. Client-side languages in comparison have been only growing better (one could make a lot of negative points about TypeScript and node in general, but the ecosystem is a joy to work with). I feel like this is because people have accepted C and C++ with their respective pain points for close…

Fast, garbage collected with plans to add a borrow checker: dlang.

It is an absolute joy to write code in D. Only downside is people complaining it has garbage collection.

Re: Assorted Thoughts on Zig and Rust

#64
post #51
post #37

Earlier quoted context omitted.

I am still torn about this. I can see the usefulness of it from python and go, but I also fear that it brings an unnecessary large maintenance burden. Http standards are evolving and soon the implementation will get stale, being in the standard library there will be need to updated it and possibly maintain backwards compatibility, even when it becomes clear that a new design may be a better option. So, suddenly peopl…

> I am still torn about this. I can see the usefulness of it from python and go, but I also fear that it brings an unnecessary large maintenance burden. Http standards are evolving and soon the implementation will get stale, Why would it "get stale"? It doesn't get stale in Golang. If anything, being part of the standard library is a greater assurance for more eyes going into it, and not having it get stale, as oppos…

Keep in mind that a HTTP server is only useful for a subset of users, it might be an "obvious" requirement for you, but it definitely isn't for me ;) Features like this should go into libraries, but not the standard library. When looking for a Go or Python alternative, Zig doesn't immediately come to mind TBH.

Also: Go (or python) has no UI system or 3D API wrapper in the standard library, but those are (probably) useful for at least as many people as a HTTP server. Does that mean that Go should get UI and 3D-rendering support in the standard library?

Re: Assorted Thoughts on Zig and Rust

#65

I think this an argument like the following is not really meaningful: > Most of this difference is not related to lifetimes. Rust has patterns, traits, dyn, modules, declarative macros, procedural macros, derive, associated types, annotations, cfg, cargo features, turbofish, autoderefencing, deref coercion etc Nobody forces beginners to write macros. Beginners are only macros _users_. With time and experience, the ne…

> Nobody forces beginners to write macros. Beginners are only macros _users_. With time and experience, the need for macros emerges by itself, then learning them is a natural part of the process. But even then, nobody is forced to write any.

Macros in Rust aren't only confusing for beginners, because it has a completely different syntax (well, at least macro_rules! does; idk about proc macros) than the one you use for the rest of your program.

Even _if_ you draw the line between macro writers and users, you've effectively made macros a black box you're not supposed to look into. Having trouble debugging anything related to a custom derive or a macro? Too bad, macro's are hard. This is (a) not useful and (b) not necessary, as Zig clearly shows.

I think Rust made the C++ mistake of trying to accommodate everyone by having both low level control of things, but not too low level since that's dangerous, so we'll come up with some rules that you can't break, and oh by the way the rules aren't really ready yet, oh, and if you're not used to dereferencing pointers, don't worry we have this deref trait, what's a trait you say? and so on and so on.

It's effectively a barrier to entry, which, ironically, is a thing the Rust community tries really hard to combat.

If you mix a bunch of nice colors, blue, red, green, turqouise, purple, orange, eggshell white, you just get ... brown.

Re: Assorted Thoughts on Zig and Rust

#66
i found zig when i found jai. i am not interested in non-gc language. there is no type of work that i do that would require non-gc language. but i was recently looking into them, just out of curiosity. but it's horrible. managing my own memory is something that i, as developer, have zero interest in doing. anyway, since rust is fugly af, like the fugliest syntax ever created in the history of human kind, and lacks proepr support for windows and ides, zig looks like i might give it a go once they get http in, since i mostly do networking stuff. also i am still interested in jai.

Re: Assorted Thoughts on Zig and Rust

#67
> As long as all unsafe code obeys the aliasing and lifetime rules, rust protects completely against UAF. Zig has little protection.

... now. The goal is to have full protection against UAF (in safe-mode only, of course).

Re: Assorted Thoughts on Zig and Rust

#68

I think Zig's biggest advantage is that it's just C without the warts, or footguns as is said in the Zig world. The comptime feature is probably the most exciting thing I've seen in a while. I've looked at Rust and feel it's more of a competitor to C++, Java and C#. Whereas Zig is C done right.

Yes. I think Zig is a safer C, while Rust is a safer C++. C programmers will be more excited by Zig than by rust, and the opposite is true for C++ afficionados.

Re: Assorted Thoughts on Zig and Rust

#69

I think this an argument like the following is not really meaningful: > Most of this difference is not related to lifetimes. Rust has patterns, traits, dyn, modules, declarative macros, procedural macros, derive, associated types, annotations, cfg, cargo features, turbofish, autoderefencing, deref coercion etc Nobody forces beginners to write macros. Beginners are only macros _users_. With time and experience, the ne…

The author is obviously in the top ~1% or something of programmers: the article is thoughtful and shows a lot of technical depth and knowledge about things most programmers won't even have heard of and he clearly has a fair amount of practical experience. So telling him he's just somehow imagining all this complexity and cognitive load, because he doesn't have to use all this complexity feels a tad tone deaf, in a very HN way.

Re: Assorted Thoughts on Zig and Rust

#70

I quite honestly wonder sometimes why Rust excited me so much when I first started using it, but I do not get such excitement from Zig. Nowadays it's very easy to be excited about Rust because it demonstrated that ownership works but when I started using it, there was still garbage collection etc. Zig looks really cool but it feels like it has a high chance of being a niche language. Rust never felt like that.

My impression was completely the opposite. I was very excited about Rust at first, especially the ownership system, but after a while I saw that it was a cleaned-up C++ with most of C++'s problems (one of the most complex programming languages in software history; very slow feedback loop). Zig, on the other hand, seems revolutionary and a complete rethinking, from the ground-up, of what low-level programming should be. True, Rust is probably 100x more popular, but is still well below 1% market adoption, so we're comparing two rounding errors in terms of adoption.
Post reply on HN