25 ms·
Please don't do "const Self = @This();" if the type isn't generic. It is pointless, redundant, ugly. What issues could public struct fields have caused?
by ptato 4y ago
Please don't do "const Self = @This();" if the type isn't generic. It is pointless, redundant, ugly.
What issues could public struct fields have caused?
- latch 4y agoSelf is used in the standard library for non generic types every now and again. As for public fields, the 0.9 change to allocator comes to mind. This was written off as a minor change, because Zig is pre 1.0. But what I haven't heard (and 100% upfront, I haven't looked hard), is how Zig plans on dealing with it post 1.0. Like, where are we in the gradient of: "1.0 will never break the public API (struct fields included)" to "deal with it".
- kristoff_it 4y ago1.0 for Zig is going to mean not only never break the API, but also that we'll be pretty much done with the language. The current idea is to release v1 only after a few releases that only contain bug fixes. > As for public fields, the 0.9 change to allocator comes to mind. That's a good example of why it makes sense for Zig to have all fields be public: the change that we did to allocators has important implications that in Zig we don't want to hide behind a `private` descriptor. This is obviously not a universal truth, but it makes sense for a low-level programming language that cares about the details. > Self is used in the standard library for non generic types every now and again. I agree with the parent poster, those should probably be removed, as they don't really help make the code more readable or provide any other advantage. A overhaul of the stdlib is planned, but we're not there yet, as we're still busy working on the package manager and incremental compilation.
- hellcow 4y agoI’d like to chime in on the all-fields-are-public debate. If I’m a library author and release something which exports a struct… I can never change any of the struct’s internal data structures? I can never rename a field. Or delete a field. Or change what should be an internal field’s type. And that makes non-breaking changes as a library author much more challenging, which may be a very serious problem for Zig, especially if the stdlib isn’t Go-style “batteries included”. I would seemingly need to version the structs to work around this: ArrayListV1, ArrayListV2… Part of the beauty of great code is in its API design. And forcing my libs to document: /// Don’t touch this field. Without any way for me to hide the field itself from users or prevent them from using it is very strange. Users can’t intuit what to use and not use without studying documentation, which a well-thought out API might improve. Go has been extremely successful in part due to its nicely thought out APIs in the stdlib. They have certain fields which anyone would care to use, and all the rest are—for your purpose as a user—not there. And this same design has made refactors of libraries/packages (without breaking changes for users) very easy.
- throwawaymaths 4y agoI work in a language where all fields are public and it is indispensable in debugging things. You DO NOT want your datatypes hiding things under the hood. At best, if zig does want to make fields private, they should still be visible, but the compiler should disallow writing to them.
- hellcow 4y agoI believe you, but I haven't encountered anything like this in my work in a higher-level language, and this is my first push into manual memory management since I studied C in college many years ago. Can you offer some examples of times when it has been indispensable, so that I can understand when this is useful?
- throwawaymaths 4y agodon't remember any off the top of my head. I use elixir, I do often dive into the data structures with IO.inspect(..., structs: false) which exposes all of the "hidden" fields. Enough so that I know how to do this without having to look it up. I suppose you could also use the debugger, but I value my time.
- kps 4y agoWhen I first played with Zig (and I haven't done more than play), I had a similar view. I suspect that the adoption of Zig in certain current C niches may be hampered by the inability to express things like the opaque pointer idiom, mandated by coding standards like CERT C and MISRA[ble] C. I now think that an external tool is the way to go. C++ has field access control, but for some projects, that's not enough, so they have an external layer of access control, like Chromium DEPS (sample: https://source.chromium.org/chromium/chromium/src/+/main:ui/DEPS https://source.chromium.org/chromium/chromium/src/+/main:ui/... ) And use cases of libraries are different. Perhaps most uses of library X use it as a black box and should never directly access structure fields, but project X′ integrates closely with X. That's hard to express in the language since it's hard to express purely within X at all. Maybe you need a `foo.@i_know_this_is_private_but_let_me_use_it_anyway(bar)`, like Python's underscore convention. Or you have an external static analyzer using some sort of allow and deny rules. Maybe library X declares `Deny *` but project X′ overrides it with an `Allow X.foo.bar`. The rules can be explicit, automatically enforced, and subject to code review, so it's OK.