News for hackers. Stuff that matters.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Sunday March 07, 2021 @06:26AM (#26375006)
Zig's main feature is what it doesn't have, and the languages you mentioned don't have that feature.

Other languages also have more-or-less general partial evaluation constructs, but they're not revolutionary because they didn't realise they can express traditional constructs in terms of partial evaluation. Zig is revolutionary in that its simple partial evaluation construct replaces generics/templates, typeclasses/concepts/traits, macros and conditional compilation. The result is something that is consistent, extremely powerful, and yet exceptionally simple.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by philosopher1234 on Sunday March 07, 2021 @02:26PM (#26378895)
Hacker news has a really hard time valuing simplicity. I think it’s an egotistical thing: I’m smart so I don’t need a simple language.

What people miss is that a simple a language allows you to apply your smarts to solving the actual problems in front of you instead of puzzling over language features. You can only handle so much cognitive load at once, and ideally the vast majority of that should be devoted to whatever problem you’re solving, not to the language itself.

Ironically, this fact is the same fact that makes complex languages more fun for hobbyists. There’s simply more to explore, and to try, and to solve, when your object isn’t building a product but instead playing with a language. It’s a different purpose, but people very rarely acknowledge this fact, likely because they’d rather pretend their purposes are clearly mechanical and business oriented. It’s ok to just want to have fun sometimes.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by the_duke on Sunday March 07, 2021 @03:02PM (#26379232)
That's an interesting observation.

It definitely has merit. I've run into this exact same thing in type-system heavy languages like Haskell/Scala/Rust, where I spend more time juggling abstractions than implementing features.

But there is an additional dimension: abstractions often make the first implementation much more cumbersome. But most code is maintained and read much more than it is written, and abstractions can make extending and maintaining a code base much easier.

It's also good to remember that the existence of certain language abstractions doesn't mean you have to use them.

You have to find the right tradeoff.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by philosopher1234 on Sunday March 07, 2021 @03:11PM (#26379329)
Another point I disagree with the consensus about! Abstractions have their place, but a bad abstraction ends up spending more of its life getting torn down than it does productively simplifying the code. In my opinion each abstraction increases system cognitive load, and so they should only be added “lazily”, ie when empirical experience with the code proves that a particular abstraction would have broad and deep utility.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Sunday March 07, 2021 @06:12PM (#26380706)
But simple languages don't mean more cumbersome abstraction -- take Scheme for example -- while C++ and Haskell's maintenance record isn't particularly great (Rust doesn't have one yet).
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by cjohansson on Sunday March 07, 2021 @04:13PM (#26379818)
In all programming languages you must understand how the parser will understand and translate what you write, it sounds like Zig will always know your intentions and maximize your code, it sounds too good to be true
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Sunday March 07, 2021 @06:08PM (#26380691)
If Zig were a high-level language it wouldn't have been so impressive. There are plenty of simple high-level languages. But in low-level domains there is a lot of extra accidental complexity because you need to precisely define layout, control memory allocation and placement, and try to avoid, or at least control branches or dynamic dispatch. And you need to do all that in the worst-case, and you don't have a JIT. So far there have been two approaches -- C, which is linguistically simple but inexpressive and spectacularly unsafe, and C++/Ada/Rust, which is much safer and much more expressive but incredibly complex. Zig finds a new way, not through some magic, but through really exceptional and radical design.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by cjohansson on Monday March 08, 2021 @01:27AM (#26382792)
But low-level languages also get translated by a parser so I don't see the difference.. Maybe you mean that languages has less abstractions and because of this simplier translations? Think I need to try Zig out to get a grip on it..
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Monday March 08, 2021 @04:01AM (#26383581)
I mean that in low-level languages the name of the game is how to work with low-level details, and Zig's design makes it exceptionally pleasant as it uses the same language for those details as it does for the logic. There is no magic here, just very clever and careful design.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by the_duke on Sunday March 07, 2021 @06:38AM (#26375066)
As mentioned in my other (wall of text) comment, that's not strictly beneficial.

It forces you to implement a lot of logic in "userspace" that other languages do for you automatically.

Complexity for certain abstractions moves from the language to user code, at the expense of consistency, cohesion, totality and (auto-generated) documentation.

It will be interesting to see how things play out for Zig once the ecosystem grows a little and libraries appear, but there are very significant downsides to this approach.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Sunday March 07, 2021 @06:53AM (#26375162)
Which of those is more beneficial indeed remains to be seen and might end up being purely a matter of personal taste; the very thing you call a downside I see as an upside. I think that talking about the positives "consistency and cohesion" where composing primitives works as a positive is merely a matter of habit. Zig treats some aspects that other languages sees as primitives as if they were any other part of the language, where code and libraries rule rather than a growing collection of primitives. I do agree that in principle a language could be too unstructured for some domains (Lisp?) but interestingly, Zig didn't go as far as syntax macros, whereas Rust did. Anyway, Zig finds a surprising middle-ground that is, as yet, hard to definitively judge, whereas Rust, for better or worse, is more of the same.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by anp on Sunday March 07, 2021 @12:03PM (#26377505)
I was thinking of The Lisp Curse[1] while reading your comment and then you mentioned the language! I’m quite excited by Zig (even if safety is lower priority for it than for Rust, it is really pushing the tooling envelope) but I do wonder whether the “anti-composition hypothesis” here holds up for relevant projects today. Many C programs include shims for compatibility between multiple different “library object models” (hell even strings count here) and they seem to be a common source of security and performance issues. Maybe in the domains where Zig is most competitive that dynamic won’t play out? Or maybe comptime provides tools that will still enable composition or at least allow for lower overhead “object model shims”? I suspect that it will be hard to know more about how it plays out until there is more language stability and code sharing, maybe even a repository like npm or crates.io.

[1] http://www.winestockwebdesign.com/Essays/Lisp_Curse.html

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by nyberg on Monday March 08, 2021 @02:25AM (#26383083)
Can the "safety is lower priority than rust" trend stop? Zig is not less concerned with safety and will catch illegal behaviour at runtime for that which isn't caught at compile-time. It's only ReleaseSmall and ReleaseFast that elide this where you're able to toggle safety checks via a builtin if you wish. There's ongoing work to provide more of it within the standard library with the GeneralPurposeAllocator being an example of it.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by anp on Monday March 08, 2021 @07:40PM (#26393742)
I'm not suggesting that Zig isn't concerned with safety, but it's not a language designed first and foremost to offer certain safety properties. For Rust you can say "as long as you don't write the `unsafe` keyword in Rust, you'll never introduce memory or thread unsafety". Is there an equivalent for Zig? Not AFAIK but I'd actually be quite happy to be shown wrong.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by dilap on Monday March 08, 2021 @08:53AM (#26385695)
Use after free is the big one Zig still doesn't protect against. Yet?

So I think it's a fair statement. Rust is safety obsessed. Zig is doing its best while paying top tribute to other gods.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Monday March 08, 2021 @02:41PM (#26390511)
I would put it differently. Rust sacrifices anything -- including things that may hurt other aspects of correctness -- to soundly guarantee (assuming the compiler is correct) no undefined behaviour in its safe subset (and yet makes some concessions, as a large percentage of Rust programs do employ unsafe code, and so don't make such a strong guarantee), while Zig finds a different balance, at times sacrificing possible UB for the sake of helping with functional correctness. Even if you look at correctness only, it is unclear which approach, if any, offers a better story.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by varajelle on Sunday March 07, 2021 @06:45AM (#26375106)
As the language evolve and people will want to do actual things with it, features will be added.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by loup-vaillant on Sunday March 07, 2021 @12:25PM (#26377700)
Assumption 1: people don't actually use Zig.

Assumption 2: the more we do with a language, the bigger the language has to be.

I am sceptical about (1), and the only way (2) can possibly be true is if the standard library is part of the language (which it really is not: it's user space stuff, curated approved by whoever's in charge). Don't be excessively pessimistic. It's just as irrational as misguided optimism.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by n30phyte on Sunday March 07, 2021 @12:40PM (#26377854)
In regards to assumption 1: zig's documentation isn't the greatest, and it's still pre 1.0 which may have turned many potential users away for the moment.

I think the person you were replying to implies that after a certain point (1.0 release?), Zig's userbase will increase to such levels that it can be considered "used" by (many) people

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by loup-vaillant on Sunday March 07, 2021 @03:21PM (#26379405)
My guess is, a few hundred users are enough to identify and correct most of what's missing in the language. Going from there to a million users is unlikely to make a big difference. Especially if the language's features are orthogonal (apparently they are), and the scope of the language is clear (the intended use case at least seems to be).

We'll see how it goes. I won't bet my hat on it, but Zig does seem to be on a good path to stay simple even as it matures.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by zozbot234 on Sunday March 07, 2021 @09:40AM (#26376161)
> Zig is revolutionary in that its simple partial evaluation construct replaces generics/templates, typeclasses/concepts/traits, macros and conditional compilation.

This is what C++98 did, except they called their one true comptime evaluation construct "templates", and they did it by accident. There's a reason why Rust introduced generics and typeclasses separately: C++98 templates as bespoke comptime evaluation was a disaster, and this was clear already in the C++ community.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Sunday March 07, 2021 @09:44AM (#26376188)
> This is what C++98 did, except they called their one true comptime evaluation construct "templates", and they did it by accident.

Right, except not at all, because templates' syntactic elements are distinct from the "object" part of the language, so it is not a partial evaluation construct for C++, but rather a separate (and rather complex) meta-language for C++. In Zig there is just Zig (with its superb error reporting mechanism), and comptime partially evaluates it. Zig distances itself from C++'s problematic design much more than Rust, which, when all is said and done, is pretty darn similar to C++.

But that's the problem with revolutionary design. Your ability to compare it to what came before it is limited because it isn't really similar to anything. Luckily, Zig can be fully learned in a day or two, so there's no need to rely on comparisons for long. You can quickly learn it and decide if it's your cup of tea or not; even if it isn't, you'd have learned something quite refreshing and inspirational, and without spending too much time.

I do agree that there is something more mysterious about Zig. Nobody knows how "good" Rust is yet, either, but it's probably no worse than C++ when we factor all elements that matter to C++/Rust developers, and we're willing to accept that it's also probably not drastically better, except maybe when it comes to undefined behaviour. Zig is more of an unknown because it is so different. It has the potential to be worse than C++, but it can also be much better. At the very least, it is very interesting in that it offers a completely new vision for how low-level programming could be done.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by roca on Monday March 08, 2021 @08:18AM (#26385372)
I really don't understand why someone would think Rust is "pretty darn similar to C++". I think about my code and data in Rust very differently to C++. C++ doesn't have tagged unions, Rust does. C++ does have inheritance, Rust doesn't. C++ templates are quite unlike Rust generics. Rust enforces safety and (mutable XOR shared), C++ doesn't. All of these lead to quite different design decisions for same-shaped problems.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Monday March 08, 2021 @02:13PM (#26390166)
You're looking at the details, while I look at the overall "feel" and find them almost indistinguishable. They're both low-level languages -- and so, like all low-level languages, suffer from low-abstraction, i.e. the difficulty to hide internal implementation details from consumers behind APIs -- that decided to invest their complexity budget to get the appearance of high-level code once you read it on the page (while the difficulty of changing it is the same as with all low-level languages), and don't hesitate to employ a fair bit of implicitness, grow a large set of features, and let compilation be slow. The details of how they do that are less important; what's most apparent is their shared design philosophy of low-level programming (although I think that Rust improves on C++ and certainly cleans it up). Zig offers a radically different approach, and one that is also radically different from C's philosophy.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by roca on Monday March 08, 2021 @02:53PM (#26390647)
I don't think your critiques are accurate, but anyway, the "similarity" here is that you have the same high-level critique of both languages. This does not make Rust "pretty darn similar to C++".

For me, memory and data-race safety and absence of undefined behavior are critical features, but it would be misleading if I were to go around saying "C, C++ and Zig are all pretty darn similar".

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Tuesday March 09, 2021 @05:48AM (#26397488)
> the "similarity" here is that you have the same high-level critique of both languages.

The similarity is that they both espouse the very same design philosophy for low-level programming. It's a pretty big similarity.

> For me, memory and data-race safety and absence of undefined behavior are critical features, but it would be misleading if I were to go around saying "C, C++ and Zig are all pretty darn similar".

It would be misleading, because memory safety and undefined behaviour in Zig is much closer to Rust than to C++. Even where it's not the same as Rust, it's still very different from C/C++. Safety and correctness are as emphasised in Zig as in Rust; they just go about achieving them differently. It is not clear at all which of them achieves correctness better.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by roca on Tuesday March 09, 2021 @05:50PM (#26405525)
> Safety and correctness are as emphasised in Zig as in Rust

This is so far from true I cannot take you seriously.

Zig doesn't have any kind of lifetime analysis, so it's as vulnerable to use-after-free/dangling pointers as C and C++ are. That alone rules out Zig from ever being considered "memory safe" in any meaningful sense.

[Yes, I'm aware of GeneralPurposeAllocator, but that is not something you want to ship in production. "Never reuse any virtual address space" is a disaster for the OS (VMA fragmentation, TLB shootdown IPIs) and the hardware (TLBs, caches). That's why no-one ships such a thing in production for C/C++. GeneralPurposeAllocator will no doubt be useful for debugging (though less effective than ASAN or Valgrind) but safety in production is the game here; ASAN doesn't make C/C++ "memory safe".]

Zig also allows data races so Zig programs can have undefined behaviour via data races on non-atomic values. Again, this cannot be fixed.

Even smart pointers (e.g. reference counting) are nasty in Zig. Zig doesn't have destructors so cleaning up an owning pointer or a refcounting pointer requires developers to write manual "defer" statements. Worse, these only work at function scope so you also have to write manual cleanup code for every data structure containing a smart pointer. Without idiomatic smart pointers Zig will likely be more prone to UAF bugs (and leaks) than C++.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Tuesday March 09, 2021 @06:07PM (#26405706)
You've misunderstood. There is no doubt that Rust eliminates more undefined behaviour than Zig (though not completely), but it does it at the cost of harming other aspects of correctness. Zig does not try to eliminate UB as much as Rust, but it focuses more on reducing other types of bugs. At the end of the day, you don't care if your program fails due to UB or another bug, and it is unclear which approach results in more correct programs overall.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by roca on Tuesday March 09, 2021 @06:24PM (#26405827)
> you don't care if your program fails due to UB or another bug,

Actually you do, because memory safety bugs are more likely to be exploitable than some arbitrary correctness bug, because they can be weaponized to take full control of the program.

The reality is that UAF/dangling pointers are a major source of CVEs in mature software. Rust prevents those in practice, Zig doesn't. You think Zig is going to be much better than Rust at preventing other kinds of bugs. I see zero evidence of that.

Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Tuesday March 09, 2021 @06:46PM (#26406016)
I don't think Zig is going to be better than Rust at preventing other bugs. I don't know. No one knows. Software correctness is a very tricky thing about which we don't know much more than we know. UB are a cause of many bugs, and Zig eliminates many kinds of UB; Rust eliminates more. But Zig is also better at things we also know reduce bugs: simple semantics with simpler analysability, and shorter turnaround, which means more tests. In formal methods research we also have an analogous choice of approaches: more soundness at the cost of higher complexity and effort or vice-versa. There is no point hypothesising about which works better because even the experts have no idea, and it's certainly possible they are about even. The only thing that can settle this is empirical research.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by roca on Tuesday March 09, 2021 @07:56PM (#26406520)
As someone who cares about safety in my software I'm going to take Rust's proven benefits over Zig's unproven hopes.
Re:Why I rewrote my Rust keyboard firmware in Zig: consisten... by pron on Wednesday March 10, 2021 @03:14AM (#26409005)
Again, you misunderstand. Both Zig and Rust have much less UB than C. The delta between Rust and Zig comes at a cost to language simplicity and to more testing. You're guessing that that cost's negative impact on correctness is smaller than that positive delta. It's a reasonable guess, but so is the opposite one, and neither is more proven than the other, which would be my guess (while I don't write safety-critical code these days, I worked on safety-critical realtime software where a bug or even a later response could cost the lives of many people; in such correctness-critical domains C is preferred over C++ despite being less safe), although I would even more confidently bet that the real difference, whichever way, is small.