4 ms·
You're assuming that's the style of programming others want to program in. Some people want the "ZII" approach. Your approach is a trade-off with costs which ma
by gingerBill 1y ago
You're assuming that's the style of programming others want to program in. Some people want the "ZII" approach. Your approach is a trade-off with costs which many others would not want to make. So it's not "preferable", it's a different compromise.
- iainmerrick 1y agoThat's clearly correct, as e.g. Go uses this style and there are lots of happy Go users. I want to push back on the idea that it's a "trade-off", though -- what are the actual advantages of the ZII approach? If it's just more convenient because you don't have to initialize everything manually, you can get that with the strict approach too, as it's easy to opt-in to the ZII style by giving your types default initializers. But importantly, the strict approach will catch cases where there isn't a sensible default and force you to fix them. Is it runtime efficiency? It seems to me (but maybe not to everyone) that initialization time is unlikely to be significant, and if you make the ZII style opt-in, you can still get efficiency savings when you really need them. The explicit initialization approach seems strictly better to me.
- gingerBill 1y ago> It seems to me... that initialization time is unlikely to be significant The thing is, initialization cost is a lot more than you think it is, especially when it's done on a per-object level rather than a "group" level. This is kind of the point of trying to make the zero value useful, it's trivially initialized. And in languages that are much more strict in their approach, it is done at that per-object level which means instead of the cost of initialization being anywhere from free (VirtualAlloc/mmap has to produce zeroed memory) to trivially-linear (e.g. memset), to being a lot more nested hierarchies of initialization (e.g. for-loop with constructor for each value). It's non-obvious why the "strict approach" would be worse, but it's more about how people actually program rather than a hypothetical approach to things. So of course each style is about trade-offs. There are no solutions, only trade-offs. And different styles will have different trade-offs, even if they are not immediately obvious and require a bit of experience. A good little video on this is from Casey Muratori, "Smart-Pointers, RAII, ZII? Becoming an N+2 programmer": https://www.youtube.com/watch?v=xt1KNDmOYqA https://www.youtube.com/watch?v=xt1KNDmOYqA
- iainmerrick 1y agoThat's what I was trying to get at by talking about making ZII opt-in. If you're using a big chunk of memory — say a matrix, or an array of matrices — it's a win if you can zero-initialize it cheaply or for free, sure. In JS, for example, you'd allocate an ArrayBuffer and use it immediately (via a TypedArray or DataView). But still, in other parts of the program, ZII is bad! That local or global variable pointing at an ArrayBuffer should definitely not be zero-initialized. Who wants a null pointer, or a pointer to random memory of unknown size? Much better to ensure that a) you actually construct a new TypedArray, and b) you don't use it until it's constructed. I guess if you see the vast majority of your action happening inside big arrays of structs, pervasive ZII might make sense. But I see most of the action happening in local and temporary variables, where ZII is bad and explicit initialization is what you want. Moving from JavaScript to TypeScript, to some extent you can get the best of both worlds. TS will do a very good (though not perfect) job of forcing you to initialize everything correctly, but you can still use TypedArray and DataView and take advantage of zero-initialization when you want to. ZII for local variables reminds me of the SmallTalk / Obj-C thing where you could send messages to nil and they're silently ignored. I don't really know SmallTalk, but in Obj-C, to the best of my knowledge most serious programmers think messages to nil are a bad idea and a source of bugs. Maybe this is another aspect where the games programming mindset is skewing things (besides the emphasis on low-level performance). In games, avoiding crashes is super important and you're probably willing to compromise on correctness in some cases. In most non-games applications, correctness is super important, and crashing early if something goes wrong is actually preferable.
- gingerBill 1y agoMaking it opt-in, means making the hierarchical approach the default. Whatever you make "opt-in" means you are by default discouraging its use. And what you are suggesting as the default is not what I wanted from Odin (I am the creator by the way). I normally say "try to make the zero value useful" and not "ZII" (which was a mostly jokey term Casey Muratori came up with to reflect against RAII) because then it is clear that there are cases when it is not possible to do ZII. ZII is NOT a _maxim_ but what you should default to and then do something else where necessary. This is my point, and I can probably tell you even more examples of where "ZII is bad" than you could think of, but this is what is a problem describing the problem to people: they take it as a maxim not a default. And regarding pointers, I'm in the camp that nil-pointers are the most trivial type of invalid pointer to catch empirically speaking. Yes they cause problems, but because how modern systems are structured with virtual memory, they are empirically trivial to catch and deal with. Yes you could design the type system of a language to make nil-pointers not be a thing unless you explicit opt into them, but then that has another trade-off which may or may not be a good thing depending on the application. The Objective-C thing is just a poorly implemented system for handling `nil`. It should have been more consistent but wasn't. That's it. I'd argue "correctness" is important in games too, but the conception of "correctness" is very different there. It's not about provability but testability, which are both valid forms of "correctness" but very different. And in some non-game applications, crashing early is also a very bad thing, and for some games, crashing early is desired over corrupted saves or other things. It's all about which trade-offs you can afford, and I would not try to generalize too much.