3 ms·
It seems to me that the problem the author writes about is bigger than the writer abstraction. To me it feels like the lack of interfaces* and inheritance in th
by schobers 2y ago
It seems to me that the problem the author writes about is bigger than the writer abstraction. To me it feels like the lack of interfaces* and inheritance in the Zig language hinders creating meaningful abstractions because you always have to use composition.
Alternatively you could argue that this just isn't the right approach within the boundaries of the Zig language: don't try to abstract, just provide a meaningful implementation (in the standard library) and re-use (using composition).
Note:
*) Yes, I know, you can create interfaces but this introduces lots of boilerplate code where to cast/forward pointers to their correct type/implementation. For an example, the author refers to another article: https://www.openmymind.net/Zig-Interfaces/ https://www.openmymind.net/Zig-Interfaces/.
- PaulRobinson 2y agoAs you note, within the Zig philosophy, I don't think this is a problem, I think it's an intentional feature.
- Turskarama 2y agoThere's no reason a feature can't be a problem though. Many would point out that inheritance is both. Interfaces solve most of the problems of inheritance with none of the problems. Some people would point out that you can implement interfaces yourself, but that isn't a real solution since either people won't bother or there will end up being a library everyone uses to do it. I think it's a useful abstraction and leaving it out will slow the adoption of Zig.
- metaltyphoon 2y agoThis and the everything is public in a struct is wild. The “document it” or use _ to mean “don't touch this” for a user is crazy IMO.
- throwawaymaths 2y agoeverything is public in a struct is great, otherwise sane debug printing would be impossible. there are other languages where nothing is private and operability (debugging on the fly when shit is falling down around you in prod) is unparalleled.
- metaltyphoon 2y agoRust has sane debug printing and doesn’t have to allow everything to be public. Opaque types are a thing in C for these reasons. You don’t want users of your code to depend on how it works internally.
- MrMcCall 2y agoA person who is inundated with boilerplate code doesn't (yet) understand the power of code generation. The proper technique is to "define the system", then "generate the code". Yes, it is very non-trivial and difficult, but all interesting information processing systems are always like that :-)
- nmilo 2y agoThis is exactly Zig's strength, not its problem. The flexibility/lack of interfaces allows you to choose the correct abstraction for the given task. In C++, every writer is `anytype`, in Java every writer is `AnyWriter`, in Rust every writer is `GenericWriter`. They all have tradeoffs but "fits better due to language design" shouldn't be one of the tradeoffs considered.
- josephg 2y ago> in Rust every writer is `GenericWriter`. I may be misunderstanding the article - but it looks like GenericWriter in zig still has dynamic dispatch overheads at runtime in all cases. Rust traits are more like “anytype” - since they get monomorphized by the compiler and have no runtime overhead at all. But unlike zig’s anytype, traits have excellent documentation (since they’re explicit, not implicit interfaces). Rust can also implicitly create an “AnyWriter” style object if you don’t want monomorphization via &dyn Trait. But you often don’t need to, because you can store trait objects in other structs just fine. - Though admittedly, you can do the same in zig via comptime structs. There are a lot of things I admire about zig. But for interfaces like Writer, rust’s trait system seems like the better tool. I wish zig would copy rust’s trait system into the language.
- nmilo 2y agoNo, GenericWriter takes a function at compile time and it gives you a GenericWriter struct that calls that function (at compile time), no function pointers needed.
- deleted 2y ago[deleted]
- latch 2y agoThere's definitely overhead with the GenericWriter, seeing as it uses the AnyWriter for every call except `write` (1) genericWriter - 31987.66ns per iterations appendSlice - 20112.35ns per iterations appendSliceOptimized - 12996.49ns per iterations `appendSliceOptimized` is implemented using knowledge of the underlying writer, the way that say an interface implementation in Go would be able to. It's a big part of the reason that reading a file in Zig line-by-line can be so much slower than in other languages (2) (1) https://gist.github.com/karlseguin/1d189f683797b0ee00cdb8186f23af98 https://gist.github.com/karlseguin/1d189f683797b0ee00cdb8186... (2) https://github.com/ziglang/zig/issues/17985 https://github.com/ziglang/zig/issues/17985
- cgh 2y agoIf you read the end of that interfaces article, you'll see a low-boilerplate way to get interfaces using tagged enums. There's no pointer casting etc. involved.
- remexre 2y agoThat relies on whoever's defining the Writer knowing every implementation of Writer in existence though, right? Same reason why Rust has both enums and trait objects; it's the expression problem.