News for hackers. Stuff that matters.
Re:Low-Level Optimization with Zig by dustbunny on Saturday June 07, 2025 @12:57PM (#44210874)
What interests me most by zig is the ease of the build system, cross compilation, and the goal of high iteration speed. I'm a gamedev, so I have performance requirements but I think most languages have sufficient performance for most of my requirements so it's not the #1 consideration for language choice for me.

I feel like I can write powerful code in any language, but the goal is to write code for a framework that is most future proof, so that you can maintain modular stuff for decades.

C/C++ has been the default answer for its omnipresent support. It feels like zig will be able to match that.

Re:Low-Level Optimization with Zig by haberman on Saturday June 07, 2025 @03:38PM (#44212046)
> I feel like I can write powerful code in any language, but the goal is to write code for a framework that is most future proof, so that you can maintain modular stuff for decades.

I like Zig a lot, but long-term maintainability and modularity is one of its weakest points IMHO.

Zig is hostile to encapsulation. You cannot make struct members private: https://github.com/ziglang/zig/issues/9909#issuecomment-9426...

Key quote:

> The idea of private fields and getter/setter methods was popularized by Java, but it is an anti-pattern. Fields are there; they exist. They are the data that underpins any abstraction. My recommendation is to name fields carefully and leave them as part of the public API, carefully documenting what they do.

You cannot reasonably form API contracts (which are the foundation of software modularity) unless you can hide the internal representation. You need to be able to change the internal representation without breaking users.

Zig's position is that there should be no such thing as internal representation; you should publicly expose, document, and guarantee the behavior of your representation to all users.

I hope Zig reverses this decision someday and supports private fields.

Re:Low-Level Optimization with Zig by raincole on Saturday June 07, 2025 @03:52PM (#44212144)
> Zig is hostile to encapsulation. You cannot make struct members private

Giving me strong "go doesn't need generic" vibe...

Re:Low-Level Optimization with Zig by eddd-ddde on Saturday June 07, 2025 @04:58PM (#44212617)
Just prefix internal fields with underscore and be a big boy and don't access them from the outside.

If you really need to you can always use opaque pointers for the REALLY critical public APIs.

Re:Low-Level Optimization with Zig by haberman on Saturday June 07, 2025 @05:33PM (#44212827)
I am not the only user of my API, and I cannot control what users do.

My experience is that users who are trying to get work done will bypass every speed bump you put in the way and just access your internals directly.

If you "just" rely on them not to do that, then your internals will effectively be frozen forever.

Re:Low-Level Optimization with Zig by lll-o-lll on Saturday June 07, 2025 @07:10PM (#44213311)
Or you change it and respond with “You were warned”.

I seriously do not get this take. People use reflection and all kinds of hacks to get at internals, this should not stop you from changing said internals.

There will always be users who do the wrong thing.

Re:Low-Level Optimization with Zig by jjmarr on Saturday June 07, 2025 @08:14PM (#44213585)
Let's say I'm in a large company. Someone on some other team decided to rely on my implementation internals for a key revenue driver, and snuck it through code review.

I can't break their app without them complaining to my boss's boss's boss who will take their side because their app creates money for the company.

Having actual private fields doesn't 100% prevent this scenario, but it makes it less likely to sneak through code review before it becomes business-critical.

Re:Low-Level Optimization with Zig by lll-o-lll on Saturday June 07, 2025 @10:47PM (#44214200)
You can still create modules in zig, just use the standard handle pattern as you might in c/c++. I think that many of us have worked in “large company”, and the issue you describe is not resolved with the “private” keyword. You need to make your “component/module” with a well defined boundary (normally dll/library), a “public interface” and the internals not visible as symbols.

That doesn’t save you in languages that support reflection, but it will with zig. Inside a module, all private does is declare intent.

In languages with code inheritance, I think inheritance across module boundaries is now widely viewed as the anti-pattern that it is.

Re:Low-Level Optimization with Zig by nicoburns on Saturday June 07, 2025 @05:48PM (#44212914)
> If you "just" rely on them not to do that, then your internals will effectively be frozen forever.

Or they will be broken when you change them and they upgrade. The JavaScript ecosystem uses this convention and generally if a field is prefixed by an underscore and/or documented as being non-public then you can expect to break in future versions (and this happens frequently in practice).

Not necessarily saying that's better, but it is another choice that's available.

Re:Low-Level Optimization with Zig by 9d on Saturday June 07, 2025 @05:52PM (#44212935)
[flagged]
Re:Low-Level Optimization with Zig by lll-o-lll on Saturday June 07, 2025 @07:01PM (#44213261)
Not everyone has to follow the MS approach of not breaking clients that rely on “undocumented” behavior. Document what will not be broken in future, change the rest and ignore the wailing.

It’s antithetical to what Zig is all about to hide the implementation. The whole idea is you can read the entire program without having to jump through abstractions 10 layers deep.

Re:Low-Level Optimization with Zig by dustbunny on Saturday June 07, 2025 @05:23PM (#44212773)
I don't care about public/private.
Re:Low-Level Optimization with Zig by 9d on Saturday June 07, 2025 @05:39PM (#44212859)
Andrew has so many wrong takes. Unused variables is another.

Such a smart guy though, so I'm hesitant to say he's wrong. And maybe in the embedded space he's not, and if that's all Zig is for then fine. But internal code is a necessity of abstraction. I'm not saying it has to be C++ levels of abstraction. But there is a line between interface and implementation that ought to be kept. C headers are nearly perfect for this, letting you hide and rename and recast stuff differently than your .c file has, allowing you to change how stuff works internally.

Imagine if the Lua team wasn't free to make it significantly faster in recent 5.4 releases because they were tied to every internal field. We all benefited from their freedom to change how stuff works inside. Sorry Andrew but you're wrong here. Or at least you were 4 years ago. Hopefully you've changed your mind since.

Re:Low-Level Optimization with Zig by haberman on Saturday June 07, 2025 @05:56PM (#44212962)
I agree with almost all of this, including the point about c header files, except that code has to be in headers to be inlined (unless you use LTO), which in practice forces code into headers even if you’d prefer to keep it private.
Re:Low-Level Optimization with Zig by keldaris on Saturday June 07, 2025 @07:52PM (#44213487)
There's nothing wrong with using LTO, but I prefer simply compiling everything as a single translation unit ("unity builds"), which gets you all of the LTO benefits for free (in the sense that you still get fast compile times too).
Re:Low-Level Optimization with Zig by philwelch on Saturday June 07, 2025 @06:40PM (#44213154)
> I'm not saying it has to be C++ levels of abstraction. But there is a line between interface and implementation that ought to be kept. C headers are nearly perfect for this, letting you hide and rename and recast stuff differently than your .c file has, allowing you to change how stuff works internally.

Can’t you do this in Zig with modules? I thought that’s what the ‘pub’ keyword was for.

You can’t have private fields in a struct that’s publicly available but the same is sort of true in C too. OO style encapsulation isn’t the only way to skin a cat, or to send the cat a message to skin itself as the case may be.

Re:Low-Level Optimization with Zig by 9d on Saturday June 07, 2025 @06:51PM (#44213213)
I don't know Zig so I dunno maybe
Re:Low-Level Optimization with Zig by girvo on Sunday June 08, 2025 @06:21AM (#44215991)
> But internal code is a necessity of abstraction

I just fundamentally disagree with this. Not having "proper" private methods/members has not once become a problem for me, but overuse of them absolutely has.

Re:Low-Level Optimization with Zig by unclad5968 on Saturday June 07, 2025 @06:23PM (#44213080)
I disagree with plenty of Andrew's takes as well but I'm with him on private fields. I've never once in 10 years had an issue with a public field that should have been private, however I have had to hack/reimplement entire data structures because some library author thought that no user should touch some private field.

> You cannot reasonably form API contracts (which are the foundation of software modularity) unless you can hide the internal representation. You need to be able to change the internal representation without breaking users.

You never need to hide internal representations to form an "API contract". That doesn't even make sense. If you need to be able to change the internal representation without breaking user code, you're looking for opaque pointers, which have been the solution to this problem since at least C89, I assume earlier.

If you change your data structures or the procedures that operate on them, you're almost certain to break someone's code somewhere, regardless of whether or not you hide the implementation.

Re:Low-Level Optimization with Zig by dgb23 on Saturday June 07, 2025 @07:05PM (#44213283)
> I've never once in 10 years had an issue with a public field that should have been private, however I have had to hack/reimplement entire data structures because some library author thought that no user should touch some private field.

Very similar experience here. Also just recently I really _had_ to use and extend the "internal" part of a legacy library. So potentially days or more than a week of work turned into a couple of hours.

Re:Low-Level Optimization with Zig by haberman on Sunday June 08, 2025 @12:22AM (#44214529)
Most data structures have invariants that must hold for the data structure to behave correctly. If users can directly read and write members, there's no way for the public APIs to guarantee that they will uphold their documented API behaviors.

Take something as simple as a vector (eg. std::vector in C++). If a user directly sets the size or capacity, the calls to methods like push_back() will behave incorrectly, or may even crash.

Opaque pointers are one way of hiding representation, but they also eliminate the possibility of inlining, unless LTO is in use. If you have members that need to be accessible in inline functions, it's impossible to use opaque pointers.

There is certainly a risk of "implicit interfaces" (Hyrum's Law), where users break even when you're changing the internals, but we can lessen the risk by encapsulating data structures as much as possible. There are other strategies for lessening this risk, like randomizing unspecified behaviors, so that people cannot take dependencies on behaviors that are not guaranteed.

Re:Low-Level Optimization with Zig by xboxnolifes on Sunday June 08, 2025 @02:51AM (#44215098)
> Most data structures have invariants that must hold for the data structure to behave correctly. If users can directly read and write members, there's no way for the public APIs to guarantee that they will uphold their documented API behaviors.

You can, just not in the "strictly technical" sense. You add a "warranty void if these fields are touched" documentation string.

Re:Low-Level Optimization with Zig by Ygg2 on Sunday June 08, 2025 @12:18PM (#44217875)
That's honestly horrible. It's like finding your job is guaranteed by a pinkie promise, or the equivalent.
Re:Low-Level Optimization with Zig by xboxnolifes on Sunday June 08, 2025 @08:34PM (#44220420)
Most of the world runs on a handshake.
Re:Low-Level Optimization with Zig by Ygg2 on Monday June 09, 2025 @08:22AM (#44223742)
That's not a valid argument. For most of human existence there was cannibalism and/or human sacrifices. This doesn't mean we should go back to it.
Re:Low-Level Optimization with Zig by jcelerier on Monday June 09, 2025 @08:09AM (#44223641)
isn't that the norm in many places on earth?
Re:Low-Level Optimization with Zig by pjmlp on Sunday June 08, 2025 @03:55PM (#44219143)
I prefer liability when devs misuse software with consequences for society infrastructure.
Re:Low-Level Optimization with Zig by xboxnolifes on Sunday June 08, 2025 @08:35PM (#44220426)
A language adding private fields does not add liability.
Re:Low-Level Optimization with Zig by pjmlp on Monday June 09, 2025 @03:58AM (#44222318)
Indeed, misusing the library and causing software faults does, so every stone in the way preventing misuse helps.
Re:Low-Level Optimization with Zig by the__alchemist on Sunday June 08, 2025 @09:52AM (#44217013)
Like unclad, I disagree that not having private fields is a problem. I think this comes down to programming style. For an OOP style (Just one example), I can see how that would be irritating. Here's my anecdote:

I write a lot of rust. By default, fields are private. It's rare to see a field in my code that omits the `pub` prefix. I sometimes start with private because I forget `pub`, but inevitably I need to make it public!

I like in principle they're there, but in practice, `pub` feels like syntactic clutter, because it's on all my fields! I think this is because I use structs as abstract bags of data, vice patterns with getters/setters.

When using libraries that rely on private fields, I sometimes have to fork them so I can get at the data. If they do provide a way, it makes the (auto-generated) docs less usable than if the fields were public.

I suspect this might come down to the perspective of application/firmware development vice lib development. The few times I do use private fields have been in libs. E.g. if you have matrix you generate from pub fields and similar.

Re:Low-Level Optimization with Zig by pjmlp on Sunday June 08, 2025 @03:57PM (#44219156)
One the key principles for modular software is encapsulation, it predates OOP by decades, and at least even C got that correct.
Re:Low-Level Optimization with Zig by Majora320 on Sunday June 08, 2025 @10:07PM (#44220894)
This is only a problem if you can't modify the library you're using for whatever reason (usually a bad one). If you have the source of all your dependencies, you can just fork and add methods as needed in the rare cases where you need to do this.
Re:Low-Level Optimization with Zig by mwkaufma on Saturday June 07, 2025 @06:52PM (#44213216)
> You need to be able to change the internal representation without breaking users.

Unless the user only links an opaque pointer, then just changing the sizeof() is breaking, even if the fields in question are hidden. A simple doc comment indicating that "fields starting with _ are not guaranteed to be minor-version-stable" or somesuch is a perfectly "reasonable" API.

Re:Low-Level Optimization with Zig by Dylan16807 on Saturday June 07, 2025 @10:48PM (#44214204)
The chance of someone relying on the size at an API level is extremely small. That's far less risky than exposing every field.
Re:Low-Level Optimization with Zig by nevi-me on Sunday June 08, 2025 @01:56AM (#44214852)
I'd imagine semantic versioning to be more subjective with a language that relies on a social contract, because if a user chooses to use those private fields, a minor update or patch could break their code.

It does feel regressive to me. I've seen people easily reach for underscored fields in Python. We can discourage them if the code is reviewed, but then again there's also people who write everything without underscores.

Re:Low-Level Optimization with Zig by dgb23 on Saturday June 07, 2025 @06:56PM (#44213247)
Some years ago I started to just not care about setting things to "private" (in any language). And I care _a lot_ about long term maintainability and breakage. I haven't regretted it since.

> You cannot reasonably form API contracts (...) unless you can hide the internal representation.

Yes you can, by communicating the intended use can be made with comments/docstrings, examples etc.

One thing I learned from the Clojure world, is to have a separate namespace/package or just section of code, that represents an API that is well documented, nice to use and more importantly stable. That's really all that is needed.

(Also, there are cases where you actually need to use a thing in a way that was not intended. That obviously comes with risk, but when you need it, you're _extremely_ glad that you can.)

Re:Low-Level Optimization with Zig by haberman on Saturday June 07, 2025 @11:46PM (#44214419)
I have the opposite experience. Several years ago I didn't worry too much about people using private variables.

Then I noticed people were using them, preventing me from making changes I wanted to make. So I created a pseudo-"private" facility using macros, where people had to write FOOLIB_PRIVATE(var) to get at the internal var.

Then I noticed (I kid you not) people started writing FOOLIB_PRIVATE(var) in their own code. And I can't entirely blame them, they were trying to get something done, and they felt it was the fastest way to do it.

After this experience, I consider it an absolute requirement to have a real "private" struct member facility in a language.

I respect Andrew and I think he's done a hell of a job with Zig. I also understand the concern with the Java precedent and lots of wordy getters/setters around trivial variables. But I feel like Rust (and even C++) is a great counterexample that private struct variables can be done in a reasonable way. Most of the time there's no need to have getters/setters for every individual struct member.

Re:Low-Level Optimization with Zig by raincole on Sunday June 08, 2025 @02:40AM (#44215053)
> And I can't entirely blame them

You can't blame them, but they can't blame you if you break their code.

Re:Low-Level Optimization with Zig by tayo42 on Sunday June 08, 2025 @02:48AM (#44215081)
That's pretty much why I never bother with the underscore prefix convention when using python. If someone wants to use it they'll do it anyway.
Re:Low-Level Optimization with Zig by geysersam on Sunday June 08, 2025 @03:01AM (#44215147)
It's about the contract with the users. I don't think you should worry about breaking someone using the private fields of your classes. Making a field private, for example by prefixing an underscore in Python, tells the users "for future maintainability of the software I allow myself the right to change this field without warning, use at your own peril".

If you hesitate changing it because you worry about users using it anyway you are hurting the fraction of your users who are not using it.

Re:Low-Level Optimization with Zig by haberman on Sunday June 08, 2025 @09:22AM (#44216845)
This is company code in a monorepo. If a change breaks users, it will simply be rolled back.

Everyone is brainstorming ways to work around Zig's lack of "private". But nobody has a good answer for why Zig can't just add "private" to the language. If we agree that users shouldn't touch the private variables, why not just have the language enforce it?

Re:Low-Level Optimization with Zig by SpaghettiCthulu on Sunday June 08, 2025 @12:26PM (#44217926)
Because sometimes the user really wants to access those fields, and if the language enforces them being private, the user will either copy-paste your code into their project, or fork your project and make the fields public there. And now they have a lot of extra work to stay up-to-date when compared to just making the necessary changes if those fields ever change had they been public.
Re:Low-Level Optimization with Zig by pjmlp on Sunday June 08, 2025 @04:00PM (#44219179)
That is the beauty of binary libraries, they enforce encapsulation.
Re:Low-Level Optimization with Zig by haberman on Sunday June 08, 2025 @01:53PM (#44218448)
I would be satisfied if the language supported this use case by offering a “void my warranty” annotation that let a given source file access the privates of a given import.

Companies with monorepos could easily just ban the annotation. OSS projects could easily close any user complaint if the repro requires the annotation.

This seems like a great compromise to me. It would let you unambiguously mark which parts of the api are private, in a machine checkable way, which is undoubtedly better than putting it into comments. But it would offer an escape hatch for people who don’t mind voiding their warranty.

Re:Low-Level Optimization with Zig by the8472 on Sunday June 08, 2025 @07:00PM (#44220014)
> or fork your project

If they want to ignore the API contract then that's the right response. The maintainer chose one thing to preserve their ability to provide non-breaking updates. The user doesn't care about that, now it's on them to maintain that code which they're sinking their probes into.

Re:Low-Level Optimization with Zig by geysersam on Sunday June 08, 2025 @11:01PM (#44221106)
> If we agree that users shouldn't touch the private variables, why not just have the language enforce it?

Thing is, I don't have an opinion about what users should do. That's entirely up to them and the trade offs they make in their contexts. There are scenarios where you might want to access a private field.

But it's also a question about simplicity, adding private to the language makes it bigger without imo contributing anything of practical value that can't be achieved with convention.

Re:Low-Level Optimization with Zig by magicalhippo on Sunday June 08, 2025 @05:17AM (#44215758)
I started using Boost's approach, that is keep those things public but in their own clearly-named internal namespace (be it an actual namespace or otherwise).

This way users can get to them if they really need to, say for a crucial bug fix, but they're also clearly an implementation detail so you're free to change it without users getting surprised when things break etc.

Re:Low-Level Optimization with Zig by pjmlp on Sunday June 08, 2025 @03:59PM (#44219168)
C++ precedent though, getters and setters were widely adopted in C++ frameworks before Java was even an idea.
Re:Low-Level Optimization with Zig by josephg on Sunday June 08, 2025 @04:42PM (#44219361)
> Then I noticed (I kid you not) people started writing FOOLIB_PRIVATE(var) in their own code.

If it’s in an internal monorepo, this should be super easy to fix using grep.

Honestly it sounds like a great opportunity to improve your API. If people are going out of their way to access something that you consider private, it’s probably because your public APIs aren’t covering some use case that people care about. That or you need better documentation. Sometimes even a comment helps:

    int _foo; // private. See getFoo() to read.
I get that it’s annoying, but finding and fixing internal code like this should be a 15 minute job.
Re:Low-Level Optimization with Zig by jcelerier on Monday June 09, 2025 @08:13AM (#44223675)
> After this experience, I consider it an absolute requirement to have a real "private" struct member facility in a language.

I think that's the wrong take to have. Life is much easier when you accept the reality of a world where people will do whatever they want with what you give them.

C++ has private, and so what? I've seen #define private public or even -Dprivate=public, I've seen classes with private implementation detail reimplemented with another name and all fields public & then casted, I've seen accessing types as char arrays and binary operations to circumvent this, I've seen accessing the process raw memory pages. If someone other than you can call the code, it's not yours anymore to decide what can be done with it.

What you don't owe anyone is the guarantee of things working if people stray from the happy path you outline - they want help after going astray, give them your hourly rate on fixing their mistakes.

Re:Low-Level Optimization with Zig by ants_everywhere on Saturday June 07, 2025 @09:59PM (#44214018)
You're getting a lot of responses with very strong opinions from people who talk as if they've never had to care about customers relying on their APIs.
Re:Low-Level Optimization with Zig by josephg on Sunday June 08, 2025 @04:36PM (#44219327)
It’s a trust thing.

If you can trust that downstream users of your api won’t misuse private-by-convention fields (or won’t punish you for doing so), it’s not a problem. That works a lot of the time: You can trust yourself. You can usually your team. In the opensource world, you can just break compatibility with no repercussions.

But yes, sometimes that trust isn’t there. Sometimes you have customers who will misuse your code and blame you for it. But that isn’t the case for all code. Or even most code.

Re:Low-Level Optimization with Zig by LAC-Tech on Saturday June 07, 2025 @10:28PM (#44214133)
The solution to this is to simply put an underscore before the variables you don't think others should rely on, then move on with your life.
Re:Low-Level Optimization with Zig by jenadine on Sunday June 08, 2025 @02:46AM (#44215074)
From my understanding, making stable API is impossible in Zig anyway, since Zig itself is still making breaking changes at the language level
Re:Low-Level Optimization with Zig by flohofwoe on Sunday June 08, 2025 @04:55AM (#44215688)
> Zig is hostile to encapsulation. You cannot make struct members private

In Zig (and plenty of other non-OOP languages) modules are the mechanism for encapsulation, not structs. E.g. don't make the public/private boundary inside a struct, that's a silly thing anyway if you think about it - why would one ever hand out data to a module user which is not public - just to tunnel it back into that same module later?

Instead keep your private data and code inside a module by not declaring it public, or alternatively: don't try to carry over bad ideas from C++/Java, sometimes it's better to unlearn things ;)

Re:Low-Level Optimization with Zig by the__alchemist on Sunday June 08, 2025 @09:56AM (#44217037)
Concur. Or, the in-between: Set the structs to be private if you need. I make heavy use of private structs and modules, but rarely private fields.
Re:Low-Level Optimization with Zig by jandrewrogers on Sunday June 08, 2025 @10:44AM (#44217313)
I think the bigger issue with "public" and "private" is that is insufficiently granular, being essentially all or nothing. The use of those APIs in various parts of the code base is not self-documenting. Hyrum's Law is undefeated.

C++ has the PassKey idiom that allows you to whitelist what objects are allowed to access each part of the public API at compile-time. This is a significant improvement but a pain to manage for complex whitelists because the language wasn't designed with this in mind. C++26 has added language features specifically to make this idiom scale more naturally.

I'd love to see more explicit ACLs on APIs as a general programming language feature.

Re:Low-Level Optimization with Zig by flohofwoe on Sunday June 08, 2025 @03:07PM (#44218918)
> I'd love to see more explicit ACLs on APIs as a general programming language feature.

In that I agree, but per-member public/private/protected is a dead end.

I'd like a high level language which explores organizing all application data in a single, globally accessible nested struct and filesystem-like access rights into 'paths' of this global struct (read-only, read-write or opaque) for specific parts of the code.

Probably a bit too radical to ever become mainstream (because there's still this "global state == bad" meme - it doesn't have to be evil with proper access control - and it would radically simplify a lot of programs because you don't need to control access by passing 'secret pointers' around).

Re:Low-Level Optimization with Zig by cobbal on Sunday June 08, 2025 @01:02PM (#44218115)
Why would you hand out data that gets tunneled back in?

There are lots of use cases for this exact pattern. An acceleration structure to speed up searching complex geometry. The internal state of a streaming parser. A lazy cache of an expensive property that has a convenient accessor. An unsafe pointer that the struct provides consistent, threadsafe access patterns for. I've used this pattern for all these things, and there are many more uses for encapsulation. It's not just an OO concern.

Re:Low-Level Optimization with Zig by pjmlp on Sunday June 08, 2025 @04:04PM (#44219190)
Many languages with modules, you can select which fields are public, all the way back to Modula-2, Ada 83.

And Zig still doesn't do binary modules.

Re:Low-Level Optimization with Zig by pdpi on Sunday June 08, 2025 @06:08AM (#44215946)
> The idea of private fields and getter/setter methods was popularized by Java, but it is an anti-pattern.

I agree with this part with no reservations. The idea that getters/setters provide any sort of abstraction or encapsulation at all is sheer nonsense, and is at the root of many of the absurdities you see in Java.

The issue, of course, is that Zig throws out the baby with the bath water. If I want, say, my linked list to have an O(1) length operation, i need to maintain a length field, but the invariant that list.length actually lines up with the length of the list is something that all of the other operations need to maintain. Having that field be writable from the outside is just begging for mistakes. All it takes is list.length = 0 instead of list.length == 0 to screw things up badly.

Re:Low-Level Optimization with Zig by ArtixFox on Sunday June 08, 2025 @07:36AM (#44216319)
You can have a debug time check.
Re:Low-Level Optimization with Zig by sramsay64 on Sunday June 08, 2025 @06:39AM (#44216068)
I think I mostly agree, but I do have one war story of using a C++ library (Apache Avro) that parsed data and exposed a "get next std::string" method. When parsing a file, all the data was set to the last string in the file. I could see each string being returned correctly in a debugger, but once the next call to that method was made, all previous local variables were now set to the new string. Never looked too far into it but it seemed pretty clear that there was a bug in that library that was messing with the internals of std::string, (which if I understand is just a pointer to data). It was likely re-using the same data buffer to store the data for different std::string objects which shouldn't be possible (under the std::string "API contract"). It was a pain to debug because of how "private" std::string's internals are.

In other words, we can at best form API contracts in C++ that work 99% of the time.

Re:Low-Level Optimization with Zig by jandrewrogers on Sunday June 08, 2025 @10:26AM (#44217211)
FWIW, the std::string buffer is directly accessible for (re-)writing via the public API. You don't need to use any private access to do this.
Re:Low-Level Optimization with Zig by pif on Sunday June 08, 2025 @06:56AM (#44216141)
You are right. Don't listen to the idiots!
Re:Low-Level Optimization with Zig by voidfunc on Sunday June 08, 2025 @10:59AM (#44217413)
How is this any different than Python or Ruby? You can access internals easily and people don't have a problem writing maintainable modular software in those languages.

Not to mention just about every language offers runtime reflection that let's you do bad stuff.

IMO, the Python adage of "We are all consenting adults here" applies.

Re:Low-Level Optimization with Zig by Galanwe on Sunday June 08, 2025 @12:18PM (#44217873)
> You cannot reasonably form API contracts (which are the foundation of software modularity) unless you can hide the internal representation

Python is a good counter example IMHO, the simple convention of having private fields prefixed with _/__ is enough of a deterrent, you don't need language support.

Re:Low-Level Optimization with Zig by gf000 on Monday June 09, 2025 @02:59AM (#44222034)
I believe private fields are a feature that actually increases the expressivity of a language, as per the formal definition. This one can't be replaced by some trivial, local syntactic sugar.

Of course increasing expressivity is not the end goal in itself for a PL, but I do agree with you that this (and some other, like no unused variable - that one drives me up a wall) design choice makes me less excited about the language as I would otherwise be.

Re:Low-Level Optimization with Zig by FlyingSnake on Saturday June 07, 2025 @01:24PM (#44211071)
I recently, for fun, tried running zig on an ancient kindle device running stripped down Linux 4.1.15.

It was an interesting experience and I was pleasantly surprised by the maturity of Zig. Many things worked out of the box and I could even debug a strange bug using ancient GDB. Like you, I’m sold on Zig too.

I wrote about it here: https://news.ycombinator.com/item?id=44211041

Re:Low-Level Optimization with Zig by wg0 on Saturday June 07, 2025 @03:53PM (#44212158)
Zig seems to be simpler Rust and better Go.

Off topic - One tool built on top of Zig that I really really admire is bun.

I cannot tell how much simpler my life is after using bun.

Similar things can be said for uv which is built in Rust.

Re:Low-Level Optimization with Zig by FlyingSnake on Saturday June 07, 2025 @04:43PM (#44212518)
Zig is nothing like Go. Go uses GC and a runtime while Zig has none. While Zig’s functions aren’t coloured, it lacked the CSP style primitives like goroutines and channels.
Re:Low-Level Optimization with Zig by 9d on Saturday June 07, 2025 @07:44PM (#44213447)
Zig is like a highly opinionated modern C

Rust is like a highly opinionated modern C++

Go is like a highly opinionated pre-modern C with GC

Re:Low-Level Optimization with Zig by cgh on Saturday June 07, 2025 @09:32PM (#44213937)
In a previous comment, you remarked you don’t even know Zig.
Re:Low-Level Optimization with Zig by LexiMax on Saturday June 07, 2025 @11:14PM (#44214309)
I do. I find his osmosis-based summation accurate.
Re:Low-Level Optimization with Zig by 9d on Sunday June 08, 2025 @08:55AM (#44216710)
Yay!
Re:Low-Level Optimization with Zig by 9d on Saturday June 07, 2025 @09:51PM (#44213986)
I don't.
Re:Low-Level Optimization with Zig by pjmlp on Sunday June 08, 2025 @04:07PM (#44219202)
More like Modula-2 with C like syntax.
Re:Low-Level Optimization with Zig by gf000 on Monday June 09, 2025 @03:14AM (#44222112)
Go should be as much in this discussion as JavaScript.
Re:Low-Level Optimization with Zig by raincole on Saturday June 07, 2025 @02:47PM (#44211668)
I wonder how zig works on consoles. Usually consoles hate anything that's not C/C++. But since zig can be transpiled to C, perhaps it's not completely ruled out?
Re:Low-Level Optimization with Zig by jeroenhd on Saturday June 07, 2025 @04:19PM (#44212363)
Consoles will run anything you compile for them. There are stable compilers for most languages for just about any console I know of, because modern consoles are pretty much either amd64 or aarch64 like phones and computers are.

Language limitations are more on the SDK side of things. SDKs are available under NDAs and even publicly available APIs are often proprietary. "Real" test hardware (as in developer kits) is expensive and subject to NDAs too.

If you don't pick the language the native SDK comes with (which is often C(++)), you'll have to write the language wrappers yourself, because practically no free, open, upstream project can maintain those bindings for you. Alternatively, you can pay a company that specializes in the process, like the developers behind Godot will tell you to do: https://docs.godotengine.org/en/stable/tutorials/platform/co...

I think Zig's easy C interop will make integration for Zig into gamedev quite attractive, but as the compiler still has bugs and the language itself is ever changing, I don't think any big companies will start developing games in Zig until the language stabilizes. Maybe some indie devs will use it, but it's still a risk to take.

Re:Low-Level Optimization with Zig by osigurdson on Saturday June 07, 2025 @01:49PM (#44211254)
I've dabbled in Rust, liked it, heard it was bad so kind of paused. Now trying it again and still like it. I don't really get why people hate it so much. Ugly generics - same thing in C# and Typescript. Borrow checker - makes sense if you have done low level stuff before.
Re:Low-Level Optimization with Zig by int_19h on Saturday June 07, 2025 @05:34PM (#44212831)
If you don't happen to come across some task that implies a data model that Rust is actively hostile towards (e.g. trees with backlinks, or more generally any kind of graph with cycles in it), borrow checker is not much of a hassle. But the moment you hit something like that, it becomes a massive pain, and requires either "unsafe" (which is strictly more dangerous than even C, never mind Zig) or patterns like using indices instead of pointers which are counter to high performance and effectively only serve to work around the borrow checker to shut it up.
Re:Low-Level Optimization with Zig by dwattttt on Saturday June 07, 2025 @06:08PM (#44213009)
> the moment you hit something like that, it becomes a massive pain, and requires either "unsafe" (which is strictly more dangerous than even C, never mind Zig) or patterns like using indices instead of pointers

If you need to make everything in-house this is the experience. For the majority though, the moment you require those things you reach for a crate that solves those problems.

Re:Low-Level Optimization with Zig by carlmr on Saturday June 07, 2025 @06:04PM (#44212999)
>requires either "unsafe" (which is strictly more dangerous than even C, never mind Zig)

Um, what? Unsafe Rust code still has a lot more safety checks applied than C.

>It’s important to understand that unsafe doesn’t turn off the borrow checker or disable any of Rust’s other safety checks: if you use a reference in unsafe code, it will still be checked. The unsafe keyword only gives you access to these five features that are then not checked by the compiler for memory safety. You’ll still get some degree of safety inside of an unsafe block.

https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html

Re:Low-Level Optimization with Zig by Ar-Curunir on Sunday June 08, 2025 @03:48AM (#44215393)
I’m sorry, but your comment is a whole lot of horseshit.

Unsafe rust still has a bunch of checks C doesn’t have, and using indices into vectors is common code in high performance code (including Zig!)

Re:Low-Level Optimization with Zig by creata on Sunday June 08, 2025 @06:28AM (#44216030)
> patterns like using indices instead of pointers which are counter to high performance

Using indices isn't bad for performance. At the very least, it can massively cut down on memory usage (which is in turn good for performance) if you can use 16-bit or 32-bit indices instead of full 64-bit pointers.

> "unsafe" (which is strictly more dangerous than even C, never mind Zig)

Unsafe Rust is much safer than C.

The only way I can imagine unsafe Rust being more dangerous than C is that you need to keep exception safety in mind in Rust, but not in C.

Re:Low-Level Optimization with Zig by whytevuhuni on Sunday June 08, 2025 @11:46AM (#44217666)
Not quite, you also need to keep pointer non-nullness, alignment and aliasing safety in Rust, which is very pervasive in Rust (all shared/mutable references) but very rare in C (the 'restricted' keyword).

In Rust, it's not just using an invalid reference that causes UB, but their very creation, even if temporary. For example, since references have to always be aligned, the compiler can assume the pointer they were created from was also aligned, and so suddenly some ending bits from the pointer are ignored (since they must've been zero).

And usually the point of unsafe is to make safe wrappers, so unafe Rust makes or interacts with safe shared/mutable references pretty often.

Re:Low-Level Optimization with Zig by creata on Sunday June 08, 2025 @12:05PM (#44217796)
It's just hard for me to imagine someone accidentally messing up nonnullness or aliasing, because it's really in-your-face that you need to be careful when constructing a reference unsafely. There are even idiomatic methods like ptr::as_ref to avoid accidentally creating null references.
Re:Low-Level Optimization with Zig by jplusequalt on Sunday June 08, 2025 @09:20AM (#44216837)
>which is strictly more dangerous than even C, never mind Zig

No it's not? The Rust burrow checker, the backbone of Rust's memory safety model, doesn't stop working when you drop into an unsafe block. From the Rust Book:

>To switch to unsafe Rust, use the unsafe keyword and then start a new block that holds the unsafe code. You can take five actions in unsafe Rust that you can’t in safe Rust, which we call unsafe superpowers. Those superpowers include the ability to:

    Dereference a raw pointer
    Call an unsafe function or method
    Access or modify a mutable static variable
    Implement an unsafe trait
    Access fields of a union
It’s important to understand that unsafe doesn’t turn off the borrow checker or disable any of Rust’s other safety checks: if you use a reference in unsafe code, it will still be checked. The unsafe keyword only gives you access to these five features that are then not checked by the compiler for memory safety. You’ll still get some degree of safety inside of an unsafe block.
Re:Low-Level Optimization with Zig by int_19h on Monday June 09, 2025 @10:36AM (#44224938)
The reason why it's more unsafe than C is because Rust makes a lot more assumptions about e.g. lack of aliasing that C does not, which are incredibly easy to violate once you have raw pointers.

Obviously if you can keep using references then it's not less safe, but if what you're doing can be done with references, why would you even be using `unsafe`?

Re:Low-Level Optimization with Zig by jplusequalt on Sunday June 08, 2025 @09:23AM (#44216852)
>using indices instead of pointers which are counter to high performance

Laughs in graphics programmer. You end up using indices to track data in buffers all the time when working with graphics APIs.

Re:Low-Level Optimization with Zig by int_19h on Monday June 09, 2025 @10:38AM (#44224953)
I'm not disputing that there are circumstances in which indices are as good or even better.

At the same time, if using indices was universally better, then we'd just use indices everywhere, and low-level PLs like Rust would be designed around that from the get go. We don't do that for good reasons.

Re:Low-Level Optimization with Zig by cornstalks on Sunday June 08, 2025 @09:30AM (#44216894)
(This is a reply to multiple sibling comments, not the parent)

For those saying unsafe Rust is strictly safer than C, you're overlooking Rust's extremely strict invariants that users must uphold. These are much stricter than C, and they're extremely easy to accidentally break in unsafe Rust. Breaking them in unsafe Rust is instant UB, even before leaving the unsafe context.

This article has a decent summary in this particular section: https://zackoverflow.dev/writing/unsafe-rust-vs-zig/#unsafe-...

Re:Low-Level Optimization with Zig by creata on Sunday June 08, 2025 @09:49AM (#44216992)
The author seems to mostly be talking about the aliasing rules, but if you don't want to deal with those, can't you use UnsafeCell?

Imo, the more annoying part is dealing with exception safety. You need to ensure that your data structures are all in a valid state if any of your code (especially code in an unsafe block) panics, and it's easy to forget to ensure that.

Re:Low-Level Optimization with Zig by Ygg2 on Monday June 09, 2025 @10:03AM (#44224646)
For those thinking unsafe Rust is harder than C. C standard defined just 216 unsafe rules, that you need to keep in mind at all times.
Re:Low-Level Optimization with Zig by sapiogram on Saturday June 07, 2025 @05:57PM (#44212967)
Haters gonna hate. If you're working on a project that needs performance and correctness, nothing can get the job done like Rust.
Re:Low-Level Optimization with Zig by LAC-Tech on Saturday June 07, 2025 @10:30PM (#44214144)
unless you have to do anything that relies on a C API (such as provided by an OS) with no concept of ownership, then it's a massive task to get that working well with idiomatic rust. You need big glue layers to really make it work.

Rust is a general purpose language that can do systems programming. Zig is a systems programming language.

(Safety Coomers please don't downvote)

Re:Low-Level Optimization with Zig by saghm on Saturday June 07, 2025 @11:20PM (#44214330)
What does it even mean to be able to "do systems programming" but not actually be a "systems programming language"? I would directly disagree with you, but what you're arguing is so vague that I don't even know what you're trying to claim. The only way I can make sense of this is if you literally define a "systems programming language" as C and only other things that are tightly tied to it, which I guess is fine if you like tautologies but kind of makes even having a concept of " systems programming language" pretty useless.
Re:Low-Level Optimization with Zig by bbkane on Saturday June 07, 2025 @11:23PM (#44214339)
And yet Rust in the one in the Linux and Windows kernels, so people must think it's worth the effort. https://threadreaderapp.com/thread/1577667445719912450.html is certainly a glowing recommendation
Re:Low-Level Optimization with Zig by LAC-Tech on Saturday June 07, 2025 @11:27PM (#44214351)
Kernels are big pieces of software. Rust is used for device drivers mainly, right? So in that case you write an idiomatic rust lib and wrap it in a C interface and load it in.

Actually interfacing with idiomatic C APIs provided by an OS is something else entirely. You can see this is when you compare the Rust ecosystem to Zig; ie Zig has a fantastic io-uring library in the std lib, where as rust has a few scattered crates none of which come close the Zig's ease of use and integration.

One thing I'd like to see is an OS built with rust that could provide its own rusty interface to kernel stuff.

Re:Low-Level Optimization with Zig by ArtixFox on Sunday June 08, 2025 @07:39AM (#44216334)
Hello can you point me to more information about zig's and rust's io-uring implementations
Re:Low-Level Optimization with Zig by LAC-Tech on Sunday June 08, 2025 @04:46PM (#44219383)
Hey Artix!

Zig's is in the standard library. From the commits it was started by Joran from Tigerbeetle, and now maintained by mlugg who is a very talented zig programmer.

https://ziglang.org/documentation/master/std/#std.os.linux.I...

The popular Rust one is tokio's io-uring crate which 1) relies on libc; the zig one just uses their own stdlib which wraps syscalls 2) Requires all sorts of glue between safe and unsafe rust.

github.com/tokio-rs/io-uring

Re:Low-Level Optimization with Zig by ArtixFox on Sunday June 08, 2025 @10:34PM (#44221002)
thank you!
Re:Low-Level Optimization with Zig by WD-42 on Sunday June 08, 2025 @10:20AM (#44217182)
The OS is called Redox.
Re:Low-Level Optimization with Zig by LAC-Tech on Sunday June 08, 2025 @04:47PM (#44219391)
It actually provides rust APIs to dev systems software against that run on it?

I know it's written in rust, but I am talking more specifically than that.

Re:Low-Level Optimization with Zig by dgb23 on Saturday June 07, 2025 @07:21PM (#44213357)
Both are great languages. To me there's a philosophical difference, which can impact one to prefer one over the other:

Rust makes doing the wrong thing hard, Zig makes doing the right thing easy.

Re:Low-Level Optimization with Zig by 9d on Saturday June 07, 2025 @07:41PM (#44213436)
> C/C++ has been the default

You're not really going to make something better than C. If you try, it will most likely become C++ anyway. But do try anyway. Rust and Zig are evidence that we still dream that we can do better than C and C++.

Anyway I'm gonna go learn C++.

Re:Low-Level Optimization with Zig by flohofwoe on Sunday June 08, 2025 @03:12PM (#44218945)
C++ has been piling more new problems on top of C than it inherited from C in the first place (and C++ is now caught in a cycle of trying to fix problems it introduced a couple of versions ago).

Creating a better C successor than C++ is really not a high bar.