Settings

Theme

Understanding the Odin programming language

odinbook.com

164 points by AlexeyBrin 19 days ago · 162 comments

Reader

pseudony 19 days ago

Having fun with this.

Never bought into rust (have studied, have a (mostly AI-generated app in rust).

Wrote some Zig but Odin is even less overhead for me. I first loved Zigs built-in build system but having tried to wrap/use C libraries from both, I must say I prefer Odin. Wrapping some sqlite 3 API’s for my first little Odin program - just because I need so little of the API that it seems easier this way - and speaking to C from Odin is a pleasure.

That is, imho, where Rust fails the most - the second part is the C++’ish approach to memory management (RAII) - that’s not how systems programming or games (I’m told) tend to work.

To each their own. I had some fun with Rust too, but for me, Odin seems the most appealing :)

  • frizlab 19 days ago

    Did you try Swift? Its interoperability with C (and even C++) is great IMHO.

    • hollowturtle 19 days ago

      It's GC

      • leecommamichael 19 days ago

        Pedantically I’ll say it’s reference counted, and someone else will say that’s still a form of GC and I’ll just save us the mini-thread.

        Reference counting has deterministic timing, you can run a deconstructor without registering objects for deletion and running any known finalizers (what you need to do in all GC langs I’m aware of.)

        • Someone 19 days ago

          > Reference counting has deterministic timing

          Define “deterministic timing”.

          - One object going out of scope may mean calling free once, but it also can trigger calling free billions of objects, even for the exact same object

          - Even freeing one object can have largely varying running time, e.g. to coalesce free blocks or, because it happens to be the last block in a virtual memory region, to unmap a block of virtual memory, blocking the program potentially for an arbitrary time

          - With garbage collection (as with reference counting), lots of the overhead of objects going out of scope can be moved onto a specialized thread.

          > you can run a deconstructor without registering objects

          Not requiring finalizes does make reference counting easier, yes. The downside is have to store the reference counts somewhere, and keep them up to date (enough)

          • RedComet 18 days ago

            "- One object going out of scope may mean calling free once, but it also can trigger calling free billions of objects, even for the exact same object

            - Even freeing one object can have largely varying running time, e.g. to coalesce free blocks or, because it happens to be the last block in a virtual memory region, to unmap a block of virtual memory, blocking the program potentially for an arbitrary time"

            So, like C, C++, or anything else that you wouldn't call garbage collected.

          • AnimalMuppet 19 days ago

            Well, GC has indeterminate timing in and of itself. Reference counting does not. It can still trigger indeterminate timing if the destructor calls free, or if the "thing" going out of scope is a pointer, but that's on the destructor or the pointer, not on reference counting per se.

            • Someone 18 days ago

              > but that's on the destructor or the pointer, not on reference counting per se.

              It is on reference counting per se. If the reference count of a reference goes to zero, the runtime has to make the memory available for reuse. That’s what I called ‘calling free’.

              Also, about “GC has indeterminate timing in and of itself”. Again: define what you mean by it. Yes, The timing of allocating an object can vary depending on the state of your memory allocator, but that’s the same with reference counting.

              (even allocating an object on the stack and then writing to it can have variable timing on many OSes. If you look really close, even decreasing a stack pointer can have variable timing on modern pipelined CPUs due to data dependencies)

              And as I said, the GC work to find and reclaim unreachable objects can run on separate thread(s).

              • AnimalMuppet 18 days ago

                I think I understand you now. You don't do reference counting for something "on the stack" (in C++ terms), you only do it for something on the heap. Things on the stack can have destructors, but that gets called when the stack frame goes out of scope. So anything reference counted, when the count goes to zero, will not only have its destructor run, but will also be deallocated on the heap (calling free).

                And then whether you blame that on reference counting or garbage collection or heap allocation is kind of an arbitrary distinction.

                OK, I get it. You were right :-)

        • frizlab 19 days ago

          Yes, but only classes are GC (refcounted as parent comment says, indeed). structs and other elements are not.

          You can even use the same ownership model as rust (borrowing et al.) with non copyable types.

  • CyberDildonics 19 days ago

    That is, imho, where Rust fails the most - the second part is the C++’ish approach to memory management (RAII) - that’s not how systems programming or games (I’m told) tend to work.

    What does this mean? Who told you that?

    • dustbunny 19 days ago

      Casey Muratori and Jon Blow have pushed this concept frequently.

      They largely don't deeply elaborate, which is sad because I am a professional game developer who is interested in precisely presented knowledge so I can apply it to my work.

      My interpretation is that games want to allocate large pools of resources, like GPU buffers, cpu memory, etc, and reuse that memory over and over. Ie: Reinitialize it.

      In my experience, RAII is my preferred pattern for certain things (std::lock_guard), and you can almost certainly express the majority of these "uber game dev patterns" using RAII/smart pointers/etc, but the c++ implementation of these "uber game dev patterns" tends to be more complicated (and imo esthetically ugly) compared to really well written C.

      These new languages (zig, odin, jai) appear to be attempts to improve C to allow an alternative to C++ that doesn't have the ugly baggage that C++ has.

      • scott01 19 days ago

        From what I understood, their critique of RAII is twofold: coupling of allocation and initialisation, and enforcement of deallocation. The ease of use of smart pointers makes it tempting to allocate/free of temporary structures even within one single function. Given enough number of such occurrences, it kills performance by a thousand cuts. Also I remember they mentioned it’s not necessary to free memory if you’re about to close your program, because the OS will take the memory back. Obviously you need to gracefully deinitialise some things, like audio or other devices, but that’s beyond the discussion.

        As on some references, Ryan Fleury did an episode on Wookash podcast on RAD debugger showing ECS like approach.

        IMO, their RAII critique is a but nuanced, but because of their personality the discourse often gets polarising.

        Edit: the sibling comment just proved my last point.

        • tancop 19 days ago

          most of that criticism only works on C++. rust does enforce RAII but uses stack allocation for locals by default instead of touching the heap so it skips the slow part.

          on the other hand there are no constructors (just normal functions) so you cant initialize values in place, only stack allocate and return. i think rust needs to add in place init and change the rules from "always init at declaration site" to "must be initialized at first use" like kotlin.

          the big missing piece is custom allocators that let you use something like a bump arena with the same convenience as system malloc. they already exist on nightly but nobody knows when they will land on stable.

          honestly thats the biggest problem with rust, they come up with a lot of useful changes but then take ages to stabilize because the core team is overworked. they also have a kind of perfectionist culture as a reaction to all the half baked features shipping in C++.

          there should be a stage between nightly and full release where feature is in stable toolchains behind a cfg flag and you get a warning if upstream crates use it. show commitment to shipping it in time but still make it clear that it can change (in minor incompatible ways) before release.

          • scott01 19 days ago

            Thanks for this, I’m actually learning Rust (albeit slowly) atm, and still can’t wrap my head around how arena allocs would fit the borrow checker

            • kibwen 19 days ago

              There are several libraries for doing arena allocation in Rust, e.g. bumpalo: https://crates.io/crates/bumpalo , see the documentation for examples (it's quite easy to use and fits the borrow checker very well). The comments in here regarding Rust are somewhat misleading; Rust doesn't require unstable/nightly features to do this sort of stuff. What's unstable in Rust right now is a standardized interface for generically working with allocators (see https://github.com/rust-lang/rust/pull/157428 for the most recent progress), including support for the containers provided by the stdlib.

            • nickmonad 19 days ago

              I haven't written any serious Rust in a while, but I assume there is some kind of lifetime annotation involved. The "objects" allocated in the arena have to be explicitly given the same lifetime as the arena itself. I have no idea how that looks syntactically.

          • whytevuhuni 19 days ago

            > honestly thats the biggest problem with rust, they come up with a lot of useful changes but then take ages to stabilize because the core team is overworked

            On the contrary, that has been one of Rust's biggest strengths. My impression when reading through stdlib was that they got so many things right, and for that to happen, things need to be thought out properly.

            Case in point, it'd be such a shame if they stabilized the allocator API, only for us to forever regret never getting the storage API [1] instead, or vice-versa, depending on which one turns out to be more pragmatic.

            > they also have a kind of perfectionist culture as a reaction to all the half baked features shipping in C++.

            And that's a good thing! Some people really dislike the constant influx of new features due to the overwhelming complexity it leads to. So if we do have new features, they better be worth it.

            [1] https://github.com/rust-lang/rfcs/pull/3446

        • CyberDildonics 19 days ago

          The ease of use of smart pointers makes it tempting to allocate/free of temporary structures even within one single function. Given enough number of such occurrences, it kills performance by a thousand cuts.

          This isn't true and doesn't make any sense. Smart pointers don't need to enter into it. If you need a lot of something you make a vector and allocate once.

          Also I remember they mentioned it’s not necessary to free memory if you’re about to close your program, because the OS will take the memory back.

          It is an extremely niche scenario to need a program to shut down so much faster that you can't even deallocate memory. If you don't make lots of small allocations in the first place the deallocations won't take any time.

          Obviously you need to gracefully deinitialise some things, like audio or other devices, but that’s beyond the discussion.

          It's actually a pretty big advantage to destructors to deal with stuff like this as well as memory and locks.

          IMO, their RAII critique is a but nuanced, but because of their personality the discourse often gets polarising.

          I think it gets polarizing because they are both undeniably sharp programmers but don't have any real evidence of this stuff, they are just grasping at rationalizations.

      • pdpi 19 days ago

        Casey Muratori and Jon Blow are both hyper-dogmatic "my way or the highway" types, and, crucially, neither of them has built any of the super high fidelity types of game that would require that level of optimisation. They're basically influencer types.

        • sarchertech 19 days ago

          Casey worked on tooling for AAA games that most certainly needed “that level” of optimization.

          Jon Blow worked on numerous AAA games that required “that level” of optimization. And he’s one of the very few developers in the last 15 years who have managed to sell more than a million copies of a game running on a scratch built 3D engine.

          You can disagree with their opinions, but they certainly have the experience to back those opinions up.

          • gf000 19 days ago

            Well, Minecraft sold far more and it's a scratch built 3d engine isn't it? Popularity is certainly not a technical achievement.

            • sarchertech 19 days ago

              Minecraft doesn't use an off the shelf engine, but I wouldn't really call Minecraft scratch built. It's built on top of LWJGL.

              Popularity isn't a technical achievement in itself. But what is a technical achievement is that he built a visually impressive 3d engine that worked well enough for over a million people to buy it at a time when almost no one else was doing this. Minecraft was released nearly 10 years earlier--before Unity and Unreal had completely taken over.

              I'm also not saying that the witness engine is somehow better than anything else out there, but it's a significant enough technical accomplishment that along with Jon Blow's other work, he has the experience to back up his opinions.

              I've also never seen the critique that Jon Blow is just an influencer with no relevant experience from anyone with equivalent relevant experience. I've seen other experienced game devs who disagree with him, but I've never seen them say that he doesn't have the experience to have them.

              • pjmlp 18 days ago

                Only because there are no native OpenGL bindings for Java from Khronos, hence LWJGL.

                • sarchertech 18 days ago

                  I don't have any experience with Java game development, but I was under the impression that LWJGL provided more than just OpenGL bindings.

                  • pdpi 17 days ago

                    Well, it's more than just OpenGL bindings mostly because it's bindings for a bazillion other things too. Just look at the javadoc[0]. The non-binding stuff in there is just utilities to make the bindings at least somewhat idiomatic in Java. In practice, LWJGL games are almost always just GLFW games, which I would still qualify as being pretty damn close to "from scratch".

                    0. https://javadoc.lwjgl.org

                  • pjmlp 17 days ago

                    It is indeed a bit like using SDL, however pure OpenGL bindings like JOGL have seen better days.

                    Also, if you are doing a game in Java, you also need bindings for sound APIs, and other ones that traditionally only care about C, thus you end up with something like LWJGL anyway.

        • torginus 19 days ago

          They really are not - there used to be whole schools of thought on how to lay out applications in memory, using the freedom of C before C++ came along, and standardized on a bunch of solutions that are controversial in some circles - stuff like vtables and exceptions are the reason C++ is banned in the kernel.

          And with things like Java, you have even less visibility. They made a ton of interviews with oldschool devs, and a most of them did things differently from how Jon and Casey do, but it's not like they disapprove, it's just with modern languages, you don't get the level of control to do this.

        • dismalaf 19 days ago

          Dunno, the Witness had gorgeous lighting. Both have consulted for AAA too.

      • torginus 19 days ago

        They might've pushed it, but they certainly didn't invent the idea. Although I'm not 100% familiar with their arguments.

        POD - objects with no behavior are pretty popular way of representing data, you can serialize and deserialize them, etc. They have a pretty big caveat in non-GC languages - if you have an object with something like a dynamic array in it, suddenly your stateless POD becomes stateful, and needs RAII otherwise you get a memory leak. No idea how they solve that without GC.

      • CyberDildonics 19 days ago

        I think those guys both hate C++ so much that they want to dismiss everything about it instead of using all the features that work for them like most people.

        My interpretation is that games want to allocate large pools of resources, like GPU buffers, cpu memory, etc, and reuse that memory over and over. Ie: Reinitialize it.

        They might say this, but there isn't a good technical rationalization here since anyone can create a global data structure just as easily in C++.

        • andrepd 19 days ago

          Exactly! The most interesting arguments for Rust that I've ever read have come not from people who hate C++, but precisely from people who are really into C++, because those are the people who actually recognise its shortcomings are are better positioned to give INSIGHTFUL criticism into it.

          People who are motivated by a superiority complex or by the wish to impress a herd of twitter followers hardly if ever produce a thought I want to read.

        • dismalaf 19 days ago

          Hate C++? They both use(d) it...

          • CyberDildonics 19 days ago

            I didn't say they don't know it.

            • dismalaf 19 days ago

              As opposed to using C, Rust, or something else (Jon eventually made Jai but Casey still uses C++). Obviously they don't outright hate it.

              • CyberDildonics 19 days ago

                They talk about hating it all the time and using some minimal subset because they have to, but the point here is not what these two internet personalities hate, it's that there isn't a technical rationale against being able to use destructors. They are hugely convenient but also completely easy to avoid if someone wants to.

                • dismalaf 18 days ago

                  Everyone uses a subset. Bjarne himself says he uses a subset.

                  • CyberDildonics 18 days ago

                    I also use a subset but the point, which I already preemptively explained, is that they don't have a technical explanation for ignoring this part of it.

                    It just seems to be wholesale aggravation so they want to reject things without a sound reason.

                    If someone asked me why I avoid inheritance I would go on a well thought through rant that connects real problems to the pragmatic reality of what that feature brings.

              • pjmlp 18 days ago

                See my history regarding my point of view on C or Go.

                Yet if my job requires to use C or Go, I like my paychecks, have bills to pay and being proud doesn't pay bills.

                Same thing with them, having to use C++ at work, doesn't mean they are big fans of it, indeed the very reason Jai exists is for Jonathan Blow never to use C++ again on his projects.

      • andrepd 19 days ago

        > Casey Muratori and Jon Blow have pushed this concept frequently

        Ah... The school of what I like to call "maximum opinions and minimal evidence". Aggressive arrogant dismissal of anything except their exact view (and for Muratori, you're also "woke" for good measure), coupled with a complete lack of _hard evidence_ to back up their views. In that regard, they're not unlike "investment advice" instagram influencers.

        • indy 19 days ago

          "coupled with a complete lack of _hard evidence_ to back up their views"

          Didn't Casey Muratori write a proof of concept windows terminal to highlight Microsoft's substandard implementation? And Jonathan Blow has spent the past decade+ developing his own programming language and funding the development of a game. Seems like they are backing their views.

        • christophilus 19 days ago

          I can see why you would think that about Jon Blow, though I disagree. But Casey? He has a number of thorough videos with plenty of evidence, and has never struck me as arrogant.

        • jstimpfle 19 days ago

          Apparently you're the school of dismissive person who can't even be bothered to look up their technical achievements.

          • CyberDildonics 18 days ago

            Confusing achievements in one area for evidence in another is literally an appeal to authority fallacy.

            • jstimpfle 18 days ago

              You must mean confusing achievements in the area of creating large maintainable and performant systems on the one hand, with achievements in the area of creating large maintainable and performant systems on the other hand?

              And let me incude Ryan Fleury here who graduated from Casey-school with honors, he is maybe the most impressive programmer I know. His work on the raddebugger is outstanding.

              • CyberDildonics 18 days ago

                You're still not anywhere close to the thread's topic. Hero worship isn't evidence.

                C++’ish approach to memory management (RAII) - that’s not how systems programming or games (I’m told) tend to work

                This is the statement that no one seems to be able to back up. Instead it's fans of some internet programmers saying that they must be right about everything because they shipped a game.

                I actually like hearing what they have to say, but they aren't right about this and there is no evidence or explanation here from you, them or anyone else.

                Instead you start talking about a third person making a debugger for some reason as if the solution to appealing to authority is more appealing to authority.

                • jstimpfle 18 days ago

                  > This is the statement that no one seems to be able to back up.

                  Actually there are many explanations of systemic issues arising from reliance on RAII. Both Jon and Casey are very good explaining the matters.

                  > Instead you start talking about a third person making a debugger for some reason as if the solution to appealing to authority is more appealing to authority.

                  A third person (already mentioned in a parent comment), who is creating an extremely snappy and powerful debugger using those exact approaches under discussion.

                  • CyberDildonics 18 days ago

                    Actually there are many explanations

                    So lets hear them.

                    A third person (already mentioned in a parent comment), who is creating an extremely snappy and powerful debugger

                    Who cares? They have nothing to do with anything, why are you avoiding a technical discussion of facts to talk about your favorite influencers?

                    • jstimpfle 18 days ago

                      > So lets hear them.

                      There are few people delivering more in-depth explanations of their claims, like literally thousands of hours of content. You can just look it up. If you disagree, please disagree. Personally I find what they say articulates almost 100% of my independent experience. And I do systems programming in C++ full-time (file systems / desktop app infrastructure). Personally I've made at least 9 serious attempts of building robust and maintainable systems on top of C++ features like RAII and templates and have always returned to simple straightforward C-style code. And I've had to work many times with existing C++ codebases that had bought into these features, and it always seemed like a giant waste of time, a way to add more spaghettis to a hot mess. And also, any technically convincing C++ codebase I've seen always seemed to make only very light use of C++ features. Not going to argue more here.

                      > Who cares? They have nothing to do with anything

                      Quite the opposite, it's a third person from the same circle making the same kind of claims (there are more persons), who have, contrary to what you say, actual evidence to back up their claims. You could just go ahead and check these works out yourself and see if it convinces you that the methods they claim to be better are actually better.

                      • CyberDildonics 18 days ago

                        These are classic zero evidence replies. Go and "do your own research", "look it up yourself", and then nothing but repeating your claims and not even realizing that isn't evidence.

                        Here it's actually worse, I don't even know what the specific claims you're talking about are.

                        If this was so simple and you know it so well just spell it out.

                        You can just look it up.

                        Or you can just look up what literally everyone else does and relies on in systems programming.

                        I've seen always seemed to make only very light use of C++ features.

                        So what? You not using something has nothing to do with an actual explanation of its shortcomings, you realize that right?

                        there are more persons

                        Then where is the actual evidence and explanation? Why is it so difficult even after multiple replies to have a shred of evidence or technical explanation?

                        It's you and the three guys you are fans of against the entire world of systems programming, because scope based resource management and ownership is what people need the vast majority of the time because most resource lifetimes are determined by scope.

                        If you're going to reply again, try to have some explanation of what your claim is and why it makes sense on a technical level instead of just trying to tell someone to go and prove your ambiguous claim for you.

                        Also saying that you ignoring something is somehow an explanation for why it doesn't work, is like someone claiming helicopters don't work because they don't use them to get around.

                        • jstimpfle 18 days ago

                          I told you what to check out. I'm not regurgitating this, I've done it often enough.

                          Have you spent 1 minute cloning the raddebugger, 3 seconds to build it, and 0.5 seconds to launch it, to be convinced that it is a solid product?

                          > It's you and the three guys you are fans of against the entire world of systems programming

                          What is this "entire world of systems programming"? From what I've seen, there are very few accomplished experts who would disagree a lot with what e.g. Jon/Casey/Ryan have to say.

                          What are you working on?

                          • CyberDildonics 18 days ago

                            I told you what to check out.

                            No you didn't, you have no information and don't even have links. What kind of twilight zone fever dream is this where you say nothing at all and pretend you already gave some sort of evidence. This is the no evidence playbook in a nutshell. Come up with unrelated nonsense, try to divert away from the question, tell the other person to go make your argument for you, say you already gave the evidence...

                            You had five comments and didn't even get started with confronting the actual question.

                            Have you spent 1 minute cloning the raddebugger, 3 seconds to build it, and 0.5 seconds to launch it, to be convinced that it is a solid product?

                            In what world does this have anything to do with anything being talked about? You need to focus.

                            From what I've seen, there are very few accomplished experts who would disagree a lot with what e.g. Jon/Casey/Ryan have to say.

                            From what I've seen it's every accomplished expert except for them, but that again is an appeal to authority logical fallacy which you seem to be in love with.

                            Why don't you say what it is they actually have to say about destructors? If this is so simple and your heroes already laid it all out for you, why can't you do it? Why can't you give even the simplest explanation when people have supposedly already explained it for you?

                            • jstimpfle 18 days ago

                              > If this is so simple

                              I _never_ said it was simple. It is actually very subtle, which is also why I made many attempts at integrating RAII style programming for many projects. RAII works for applications with simple lexical and local lifetimes and ownership. But it's not a good fit for more complex systems with more global and coordinated allocation and ownership patterns in my experience. The concept of ownership and lifetimes encoded by it are too simplistic (when in reality, these terms are not even well defined), as is evidenced also by the various extensions to the machinery over the years (such as exceptions, move/copy asignment/constructors, rvalue references, unique_ptr, shared_ptr, trivially_copyable, trivially_destructible...) that contributed to form the probably most complex and hard to read language out there.

                              A big part of the problem is that there is no easy migration path from a smaller program with simpler lifetime and ownership patterns (relying on RAII) to a larger program with much more complex patterns (gradually discarding RAII/reworking allocation and ownership strategies). It is hard to refactor stuff that happens "between the lines" as part of the language rules, besides being hard to read also (unless the patterns are trivial).

                              >> raddebugger

                              > In what world does this have anything to do with anything being talked about? You need to focus.

                              Like, in the world where I've referenced this in 3 of my 4 previous comments, as an example of a serious application built without RAII, which leans heavily into arenas, resulting in extremely compact and fast code?

                              > Why don't you say what it is they actually have to say about destructors?

                              Is this an exam? I referenced these guys instead of regurgitating because they can do it better, the content is out there, and I hardly could do justice to the matter in a few lines. If you need a couple more catchy but badly written phrases, it's that RAII comes at a large cost in terms of typing, and even though it automates some painful code, it will "infect" your codebase, requiring an all or nothing approach or you're actually back to manually managing memory, in fact you can not insert manual frees between arbitrary RAII destructor calls.

                              It will break modularization of your codebase, leading to subtle creeping degradation. It breaks separation/abstraction of memory management from data representation across module boundaries. This is part of what leads to long compile times that are very common with C++ code bases, as typically type definitions (including any internal matters and their dependencies) will be fully exposed in the headers instead of hidden in implementation files.

                              RAII adds temporal coupling between memory allocation and data lifetimes, which is a disadvantage as you scale your codebase up. And under the hood, RAII is still fundamentally built on a model of individual object thinking, allowing for the typical classes of memory bugs, like use-after-free if you do tree type or even spider web type object graphs (which sometimes is just what you have to do).

                              Separate allocation approaches on the other hand allow for better modularization and abstraction, and allow to handle allocation more centrally instead of cluttering allocation conerns across all types of a codebase.

                              That's it finally for me, this is a rushed summary and as said other people have explained this much better. I've also had enough of your condescending replies. Have a good day.

                              EDIT: if you are looking for text content instead of video rants, checkout https://www.dgtlgrove.com/p/untangling-lifetimes-the-arena-a... as an example of a well written treatment in this area. But really, these 3 guys (besides others) are all very good at explaining that stuff in videos too, just use google please and make up your own mind.

                              • CyberDildonics 18 days ago

                                Like, in the world where I've referenced this in 3 of my 4 previous comments, as an example of a serious application built without RAII, which leans heavily into arenas, resulting in extremely compact and fast code?

                                You bringing up something unrelated doesn't mean anything just because you keep bringing it up.

                                Do you think anyone thought that nothing can be built without RAII? Did you think that was an argument anyone was making? Do you think someone walking barefoot means shoes don't do anything?

                                Is this an exam?

                                There is one singular question and you seem to think it's absurd to answer it and not veer off into a hundred different directions about unrelated projects and your favorite influencers instead of being able to focus on it.

                                it's that RAII comes at a large cost in terms of typing

                                If it automates things why would it have a typing cost? That makes zero sense.

                                it will "infect" your codebase,

                                How? It can be used or not.

                                requiring an all or nothing approach or you're actually back to manually managing memory

                                It's completely the opposite, you can use data structures that have destructors or not use them at all, this is not only not true it doesn't even confront the utility.

                                It will break modularization of your codebase, leading to subtle but substantive degradation.

                                These are strange claims, they don't have any evidence because you didn't explain why this would be true. It nonsensical, have you ever actually used these features? What does "substantive degredation" even mean or refer to? It's just running deallocation automatically, which you already have to do.

                                This is part of what leads to long compile times

                                No it isn't, it's running the same function at the end of a scope. Where are you getting this idea? Templates you could say this about, but a simple concept has nothing to do with it.

                                RAII adds temporal coupling between memory allocation and data lifetimes,

                                "Temporal coupling" doesn't make any sense, you have to deallocate memory anyway, why would it be any different to not have to write the line explicitly?

                                Separate allocation approaches on the other hand allow for better modularization and abstraction, and allow to handle allocation more centrally instead of cluttering allocation conerns across all types of a codebase.

                                Why would this make any sense? If you want to create a global you create a global. If you aren't freeing something when you don't use it, you're creating a global whether you want to or not.

                                This whole thing reads like being at the end of a game of telephone, there are no actual explanations in here and pretty much nothing that makes sense, but at least you actually focused on the question.

                                If you want to have a real explanation, especially to yourself, you should probably show a scenario on godbolt or something like that. It really seems like people have led you down a path that doesn't make sense and you haven't gone back and tested it yourself.

                                • jstimpfle 18 days ago

                                  > You bringing up something unrelated doesn't mean anything just because you keep bringing it up.

                                  It's NOT unrelated. It is a real world demonstration of the simplicity possible by custom modeling of allocation and lifetime concerns instead of buying into a fixed scheme set by a language.

                                  > There is one singular question and you seem to think it's absurd to answer it and not veer off into a hundred different directions about unrelated projects and your favorite influencers instead of being able to focus on it.

                                  You made me do it by repeatedly talking down on me in a condescending tone, when I tried to keep it simple and referred to external sources. What the heck. You want a simple reply. I cannot give you one, except for, "RAII is this simplistic solution that makes the language complicated while still being by far not enough to handle interesting use cases. It has turned out to be wrong and misguided every time I've tried to use it, and here are a million examples why".

                                  > If it automates things why would it have a typing cost? That makes zero sense.

                                  It automates generating boring boilerplate code (which is good on one hand but it doesn't reduce the semantic complexity AT ALL, so actually it just promotes doing the wrong thing by making the wrong thing easier). To generate the boilerplate code it requires type machinery. What doesn't make sense about this?

                                  Why don't YOU start telling ME?

                                  >> it will "infect" your codebase,

                                  > How? It can be used or not.

                                  To use it e.g. in containers, you then have to also use it for the things contained -- e.g. unique_ptr<T> or vector<T> or whatever, you will have a bad time if you don't model T's destruction with a C++ destructor too. Also you can't just insert random manually managed objects within a group of RAII managed objects, because that will break the "reverse destructor calls" assumption.

                                  It's a viral thing.

                                  >> It will break modularization of your codebase, leading to subtle but substantive degradation.

                                  >These are strange claims, they don't have any evidence

                                  I explained why: internals have to get moved to public API in practice. This is almost the definition of breaking modularization.

                                  >> This is part of what leads to long compile times

                                  > No it isn't, it's running the same function at the end of a scope. Where are you getting this idea? Templates you could say this about, but a simple concept has nothing to do with it.

                                  Why are you being so stubborn? Destructors (like other methods) practically require classes to be fully exposed (that you can protect them with silly public/private/protected specifiers doesn't change the fact they're exposed), requiring includers to pick up transitive dependencies. That results in huge amount of included code per TU, and results in far too many TUs that have to be rebuilt on incremental changes.

                                  This is a very well known thing.

                                  > "Temporal coupling" doesn't make any sense, you have to deallocate memory anyway, why would it be any different to not have to write the line explicitly?

                                  Why doesn't it make sense? In practice, allocation is coupled with initialization and destruction is coupled with deallocation. It's literally in the name, Resource Allocation Is Initialization. You can work around it, sure, but it's painful and literally just an escape hook to escape the very thing you're arguing for.

                                  > If you want to have a real explanation, especially to yourself, you should probably show a scenario on godbolt or something like that. It really seems like people have led you down a path that doesn't make sense and you haven't gone back and tested it yourself.

                                  ON GODBOLT? Are you kidding me? I've been arguing all day how RAII is a simplistic rigid mechanism builtin to a language that will lead to slow creeping systemic issues, in practice, in my experience, in larger and more complicated systems, especially with performance and abstraction requirements. I CAN NOT explain to you what sucks about it in a godbolt. You can use RAII fine for simpler programs. You can use it fine in a godbolt. You can use it fine for leetcode. etc.

                                  Asking for a Godbolt example of architectural coupling is like asking for an assembly listing proving that a database schema is hard to migrate.

                                  • CyberDildonics 17 days ago

                                    It's NOT unrelated. It is a real world demonstration of the simplicity possible by custom modeling of allocation and lifetime concerns instead of buying into a fixed scheme set by a language.

                                    No, it's claiming that because someone can do something that there must not be a better way to do it. Games were written in assembly, that doesn't mean that's the best way to do it.

                                    I've been arguing all day

                                    You've been avoiding it all day then finally making claims after six replies.

                                    vector<T> or whatever, you will have a bad time if you don't model T's destruction with a C++ destructor too

                                    So? What do you think that looks like in C? For loops and nested for loops, which all need to be hand written or copy and pasted and to happen at the right time. If you start dealing with early returns or gotos you need to have all those nested for loops copy and pasted multiple times.

                                    I explained why: internals have to get moved to public API in practice.

                                    This makes no sense, you would just move something into a function if it needs to take ownership. In C you have nothing to indicate ownership and every function in every API needs to have auxiliary documentation to say whether it is going to own the memory you give it or not.

                                    Why are you being so stubborn?

                                    I keep asking for the same thing and you keep running away from it.

                                    Destructors (like other methods) practically require classes to be fully exposed

                                    This doesn't make any sense, it automates something you have to do any way.

                                    ON GODBOLT? Are you kidding me?

                                    Is there something wrong with an actual program that shows actual evidence? This seems like a basic demonstration is earth shattering to you.

                                    I CAN NOT explain to you what sucks about it in a godbolt.

                                    If you can't demonstrate it with actual source code then you just have claims and no evidence.

                                    • jstimpfle 17 days ago

                                      > If you can't demonstrate it with actual source code then you just have claims and no evidence.

                                      I can NOT demonstrate it in a tiny godbolt because the effects I am talking about don't apply on a micro-scale.

                                      I CAN demonstrate it with actual source code, but you are unwilling to look it up. You are disagreeing without making the tiniest effort. Not being willing to make an effort by itself is fine. But you're being contrarian in the worst and laziest way.

                                      Do you not understand the concept that I can't explain the world to you from the ground up? You say no to everything without trying to understand it. Your "rebuttals" indicate you're not willing to follow me in the slightest and you reject even the most common lore (for example the thing about C++ class features (destructors, methods...) leading to exposure of internals in public headers, leading to every TU including the world). Or you are intentionally trolling me. You are being uncooperative and you're the single worst interaction I've had on this platform. Now please get off my lawn.

                                      • CyberDildonics 17 days ago

                                        To recap, there are all sort of detrimental effects to just freeing memory when a variable goes out of scope, but they can't be explained or demonstrated in any way.

                                        I could tell it was all going to go this way from the second comment, I'm always fascinated by people with rock solid beliefs that can't explain them in any way.

                                        I can NOT demonstrate it in a tiny godbolt because the effects I am talking about don't apply on a micro-scale.

                                        They do because it's just automatic resources within a scope.

                                        I CAN demonstrate it with actual source code, but you are unwilling to look it up.

                                        Why don't you link something besides a name of a big C project and explain it. The idea that someone making a project in C somehow means other features and tools are terrible isn't even logic. That would mean that one project in a language from the 70s would negate every garbage collected and dynamically typed scripting language. It makes no sense in any way. It's like saying because someone road a bike 20 miles cars are terrible.

                                        Do you not understand the concept that I can't explain the world to you from the ground up?

                                        You don't seem to be able to explain anything at all.

                                        You say no to everything without trying to understand it.

                                        You don't give any explanations, they are just claims, do you understand that? Do you know what evidence is? It's the thing you say you can't provide.

                                        You think that somehow something simple like automatically running a function you have to run anyway is a problem, it's nonsense.

                                        By your own logic the fact that https://github.com/chromium/chromium has 1.7 million commits to your project's 4,385 means that modern C++ is more than 380 times as effective.

                                        for example the thing about C++ class features (destructors, methods...) leading to exposure of internals in public headers

                                        That's a matter of dependencies and doesn't have anything to do with destructors.

                                        you're the single worst interaction I've had on this platform.

                                        Now we're to the "I don't like how you're saying it" part of the no evidence playbook. This happens when someone can't admit that they don't have any information and they can't believe that people won't accept them repeating claims as evidence.

                                        Your own project has plenty of the bugs that destructors and contained memory allocation avoid. Raw heap allocations, raw mem copies etc.

                                        https://github.com/EpicGames/raddebugger/issues/855

                                        Here's a complex memory cleanup race condition that's 'solved' with a sleep function. https://github.com/EpicGames/raddebugger/issues/735

                                        even the most common lore

                                        I think it's time to admit to yourself that you have accepted some internet youtuber personalities as a religious belief and that you haven't questioned these beliefs with thoughts that go beyond the claims of the cult.

                                        • jstimpfle 17 days ago

                                          > Your own project

                                          First, tone it down a little please, would you? It's not "my project", what is wrong with you?

                                          > ... has plenty of the bugs that destructors and contained memory allocation avoid. Raw heap allocations, raw mem copies etc. https://github.com/EpicGames/raddebugger/issues/735 . Here's a complex memory cleanup race condition that's 'solved' with a sleep function. https://github.com/EpicGames/raddebugger/issues/855

                                          Now you've provided two links and they contain little evidence to back up your claims. Linking issue 735 suggests that you've misunderstood the part about a "Sleep", which evidences either your lack of capacity to grok the context of the issue, or evidences your unhealthy adversarial stance (I strongly suspect the latter).

                                          > You don't give any explanations, they are just claims, do you understand that? Do you know what evidence is? It's the thing you say you can't provide.

                                          You haven't been able to take the most obvious uncontentious claim from me. But if I'm not explaining as you say, what are YOU doing?

                                          Are you seriously too stubborn to accept that exposing a destructor (or any other method) in a header file requires exposing the class's definition (private method declarations including signatures, include internally used headers for internally used data structures, which again have methods, which have dependencies...) in C++? And when any of those not-real-dependencies changes, you have to rebuild everything needlessly? Are you somehow mentally unable to see how long compile times can subtly degrade a project over time?

                                          Because I didn't need any youtuber personality to find that out for myself. And for some humility, the fact that I was able to see that suggests it's not particularly hard to find out.

                                          > Why don't you link something besides a name of a big C project and explain it. The idea that someone making a project in C somehow means other features and tools are terrible isn't even logic. That would mean that one project in a language from the 70s would negate every garbage collected and dynamically typed scripting language.

                                          And also I didn't claim it, you fantasized it and I can't help but ridicule you for having such wild ideas. To make such claims you would actually have a closer look at a project.

                                          > By your own logic the fact that https://github.com/chromium/chromium has 1.7 million commits to your project's 4,385 means that modern C++ is more than 380 times as effective.

                                          How is that by my own logic? But please accept that this is the work of mainly 1-2 persons, and compare _hours_ of build time (35 MLOC) to 3 seconds of build time (300K LOC).

                                          > You think that somehow something simple like automatically running a function you have to run anyway is a problem, it's nonsense.

                                          You are misrepresenting what I've said so badly it's not funny anymore. I've said multiple times that maybe this function shouldn't even exist. And even if the function has to exist, maybe it shouldn't be coupled so hard, at a language level, with the actual state & logic definitions. I did provide reasons why I've perceived the coupling to be an architectural problem.

                                          I would be very open to a discussion when this can or can not be a serious problem and what are possible tradeoffs and points in the design space. It wouldn't make me feel bad and wouldn't take away from my claim that there is actual evidence for the issues being discussed. But with a person like you, that's not possible.

                                          > That's a matter of dependencies and doesn't have anything to do with destructors.

                                          I've explained multiple times why I think it does. If you want a destructor declared in C++, you have to give the full class definition.

                                          > Now we're to the "I don't like how you're saying it" part of the no evidence playbook. This happens when someone can't admit that they don't have any information and they can't believe that people won't accept them repeating claims as evidence.

                                          No, it happens when I can't believe how you haven't managed to stop talking down on me instead of making an effort to be anything other than an annoying adversary. That's all.

                                          > I think it's time to admit to yourself that you have accepted some internet youtuber personalities as a religious belief and that you haven't questioned these beliefs with thoughts that go beyond the claims of the cult.

                                          I think it's time for you to shut up. You are providing zero evidence for your baseless (even counter-factual) accusations towards myself. What you say makes ZERO sense.

                                          • CyberDildonics 17 days ago

                                            First, tone it down a little please,

                                            I think it's time for you to shut up

                                            you fantasized it

                                            your lack of capacity to grok the context of the issue

                                            Now we're firmly into the insults phase. You can just admit that you don't know about something or that you don't have evidence, or you can ask questions, but resorting to insults instead of just saying "I don't know" or "I haven't considered that" or "I'm fine with what I'm using so I haven't worried about what other people are doing" is unfortunate.

                                            you've misunderstood the part about a "Sleep"

                                            I repeated what was in the comments. This is another example of claims without evidence, you realize that right? You didn't explain it and how I was wrong, you just said "no, nu uh".

                                            3 seconds of build time

                                            Are you talking about build times now? What happened to all the stuff about being terrible for the APIs and so toxic for the whole system that you can't write anything in godbolt?

                                            how you haven't managed to stop talking down on me

                                            Now it's time to play both sides and fling insults but pretend that me asking for evidence is talking down to you.

                                            I've explained multiple times why I think it does. If you want a destructor declared in C++, you have to give the full class definition.

                                            Finally an explanation of some sort. Too bad this isn't true. Do you know that the implementation can be in a compilation unit just like C?

                                            you are providing zero evidence for your baseless (even counter-factual) accusations towards myself. What you say makes ZERO sense.

                                            You believe things without evidence and you have said where they come from. Then when asked for evidence you grasp at anything from insults to completely unrelated things like a single program that you like which demonstrates nothing. Those are the actual facts.

                                            • jstimpfle 17 days ago

                                              > Now we're firmly into the insults phase.

                                              We have been from about your 2nd comment on.

                                              > "I haven't considered that"

                                              Considered WHAT?

                                              > I repeated what was in the comments. This is another example of claims without evidence, you realize that right? You didn't explain it and how I was wrong, you just said "no, nu uh".

                                              I was merely giving you a second chance to notice by yourself that the Sleep-Code in question is code that is being debugged, not part of this project. But instead of double checking, again you've been relentlessly continuing on your trajectory.

                                              You've ended up furthering your wild accusations without entertaining the possibility that I might be not completely wrong on all fronts, and you might be only half right (or less).

                                              > Are you talking about build times now? What happened to all the stuff about being terrible for the APIs and so toxic for the whole system that you can't write anything in godbolt?

                                              It's one of the topics, one of the manifestations of the systemic issues I was talking about, if you had paid any sort of attention.

                                              > Finally an explanation of some sort. Too bad this isn't true. Do you know that the implementation can be in a compilation unit just like C?

                                              You are still not understanding? I gathered you seem to be a game developer of some sorts but you don't understand the simplest basic facts about C++?

                                              Please show me how you can call a destructor in C++ without seeing the declaration of the destructor. (I mean calling it directly of course, since calling it indirectly would refute your claim that a destructor is needed -- since you can't have an arbitrary intermediate function called automatically by RAII).

                                              Or show me how you can see the declaration of the destructor without seeing the definition of the class.

                                              JUST DO IT. SHOW THE EVIDENCE. DONT TALK.

                                              • CyberDildonics 17 days ago

                                                We have been from about your 2nd comment on.

                                                Nope, if you think forming beliefs from youtubers is so negative, don't do it.

                                                It's one of the topics, one of the manifestations of the systemic issues I was talking about, if you had paid any sort of attention.

                                                Nope, destructors have nothing to do with this and this was never something you mentioned before. If it was you could show it with godbolt.

                                                You are still not understanding? I gathered you seem to be a game developer of some sorts but you don't understand the simplest basic facts about C++?

                                                Show me. They are just functions, usually one or two lines.

                                                Please show me how you can call a destructor in C++ without seeing the declaration of the destructor.

                                                You have declarations of functions the same as in C, did you try this?

                                                JUST DO IT. SHOW THE EVIDENCE. DONT TALK.

                                                Show me what you're talking about in godbolt.

                                                • jstimpfle 17 days ago

                                                  > Nope, destructors have nothing to do with this and this was never something you mentioned before. If it was you could show it with godbolt.

                                                  How about you simply Ctrl+F for "build time" or "compile time" and admit you have been lying, have been extremely adversarial, and have been incredibly lazy?

                                                  > Show me. They are just functions, usually one or two lines.

                                                  Isn't it strange that I'm now creating a godbolt containing absolute C++ basics as a youtuber personality fangirl, since apparently I'm only repeating stuff I don't understand, which has to be why I can't express myself and provide evidence?

                                                  It is beyond me how you don't seem to know what I'm talking about, but here you go... This should provide reasonable evidence of the lack of ergonomics when using C++, and how problematic this class stuff is from various technical standpoints.

                                                  As you mentioned, in C style programming, we could instead simply forward declare a struct, than forward declare some functions. One line for each. Good header hygiene. Clean. Done. But noo, this is C++ and we can't have straightforward code and low coupling.

                                                  Full link: https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaP...

                                                  • CyberDildonics 17 days ago

                                                    How about you simply Ctrl+F for "build time" or "compile time" and admit you have been lying, have been extremely adversarial, and have been incredibly lazy?

                                                    More insults but there is no difference here.

                                                    I looked at your godbolt link, which part of this does C avoid? Is your whole argument here that you have to define a class' data even though you have to do the same thing in C?

                                                    Is it your argument against an optional feature seriously that you can't use the PIMPL pattern from the 90s ? Holy mother of god, that's what is so important? Every struct and class definition you have ever written compiles in a fraction of a second on hardware from 15 years ago this makes no sense at all. It even took you an entire novel of "nu uh" and "this program was written in C so everything else is bad" to get there.

                                                    What happened to all the toxic program destroying architecture effects? Now it boils down to something that is no different but without it all the same memory bugs persist.

                                                    • jstimpfle 16 days ago

                                                      > More insults but there is no difference here.

                                                      Rebutting your wild and easily disproved claims where it's necessary.

                                                      > I looked at your godbolt link, which part of this does C avoid?

                                                      Should I spell it out again for you? With non-class programming, you can do

                                                          struct Foo;
                                                          struct Bar;
                                                          Bar *bar_create();
                                                          void bar_destroy(Bar *bar);
                                                          void foo_doThing(Foo *foo);
                                                          Foo *foo_create(int x, int y, Bar *bar);
                                                          void foo_destroy(Foo *foo);
                                                      
                                                      And that's literally the API, clean and readable. Now granted, it doesn't do RAII, but here's the essence of the API, in a form that you can actually improve and develop and refactor, and which doesn't require you to rebuild the world if you changed something in a remote corner of the codebase.

                                                      This is super well known common lore, and if you haven't noticed this yourself and haven't heard many people talking about this, you simply don't know what you're talking about.

                                                      > Every struct and class definition you have ever written compiles in a fraction of a second on hardware from 15 years ago this makes no sense at all.

                                                      I'm not repeating once again how this requires you to include the world for the smallest thing which is extremely painful.

                                                      > Is it your argument against an optional feature seriously that you can't use the PIMPL pattern from the 90s ? Holy mother of god, that's what is so important? Every struct and class definition you have ever written compiles in a fraction of a second on hardware from 15 years ago this makes no sense at all. It even took you an entire novel of "nu uh" and "this program was written in C so everything else is bad" to get there.

                                                      This is not about single-build times (which are much more affected by by template metaprogramming), but about quadratic incremental rebuild scaling. And "in a fraction of a second" is a ridiculous argument when it's well known that C++ single build times are spectacularly bad and developers have to wait way too much for clean rebuilds too.

                                                      You just don't get it. And no, you don't do PIMPL. It doesn't scale at all. It's realistic to PIMPL a plain struct once in a while, but NOT with C++ classes with methods etc on a regular basis. It's not ergonomic to do so, it requires even much more boilerplate to do the simplest thing, and it makes it incredibly hard to change and fix and evolve anything. Plus, PIMPL does add a runtime indirection btw. It's BAD.

                                                      Again, I know what I'm talking down not because I'm repeating what "my heroes" said but because I've actually tried to make it work, many times. It doesn't work. And you're not doing PIMPL either. Want to know how I know? BECAUSE IT DOESN'T WORK AND YOU ARE JUST TALKING.

                                                      > Now it boils down to something that is no different but without it all the same memory bugs persist.

                                                      You can't be serious. Now you claim that's the only thing I said? No, I've said many other things. You're a loudmouth who doesn't understand the most basic thing, so we have to spend days before you accept the tiniest straightforward common sense argument that you could just google. Do you want to go down the next rabbit hole? Because I don't, I'm so done with you.

                                                      • CyberDildonics 16 days ago

                                                          Bar *bar_create();
                                                          void bar_destroy(Bar *bar);
                                                        
                                                        Now you have a destructor, you just have to remember to run it when the pointer goes out of scope. If you have early returns, error handling gotos, better remember to put in all the right places and none of the wrong places. At least in this scenario you know you own the memory. If you aren't making and destroying the data structure pointer and you just get it from a function or another data structure what now? Do you destroy it or is it just a reference? What function do you use? Time to check the header file and the documentation, hopefully that exists.

                                                        Not only that, but you have a pointer to the structure instead of it living on the heap. Now you have unnecessary indirection, allocation and pointer chasing when in C++ you could just treat it like a value. If you have a heap allocation in there you are now hopping from one pointer for the struct allocation to another pointer for the actual data allocation.

                                                        With your API you created an object with none of the huge advantages of being able to treat it like every other value in modern C++.

                                                        Everyone figured out how fragile this was since it started 50 years ago. Decades ago people worked out that the same problems happened constantly and came up with solutions which brought us (most of us) to where we are now.

                                                        This is not about single-build times

                                                        Now it's not about build times? I thought it was and you had said that all along? Now the story changes again.

                                                        I'm not repeating once again how this requires you to include the world for the smallest thing which is extremely painful.

                                                        Nope. You only need a class definition. Definitions don't take up any compilation time.

                                                        And "in a fraction of a second" is a ridiculous argument when it's well known that C++ single build times are spectacularly bad and developers have to wait way too much for clean rebuilds too.

                                                        People don't get themselves into bad build times because of simple class definitions. All 6MB of sqlite compiles in a single second. When people have C++ build time problems it's because of templates.

                                                        you don't do PIMPL.

                                                        I never said I did, I avoid it because that's basically what you are doing here.

                                                        Plus, PIMPL does add a runtime indirection btw

                                                        You added one already. PIMPL is the same as your indirection from heap allocating a predeclared struct so that you can return it from your constructor. The price is heap allocation and indirection.

                                                        I've said many other things.

                                                        You have, not all of them on topic.

                                                        You're a loudmouth

                                                        This is text.

                                                        • jstimpfle 16 days ago

                                                          It's long been clear that you don't understand what you're talking about when you're criticizing what I say. You don't realize that I understand everything you say and I'm only explaining where your line of reasoning breaks. The concerns you raise are beginner level C++ object thinking. You still haven't understood what I've said. It has turned out that the actual zealot is you, you're just a follower of mainstream ideology, following conventions without understanding them. Being part of the mainstream seems to mean you feel legitimized to talk down on others who are looking for solutions to genuine, serious problems. Following the mainstream will give you predictable results, but also with a low ceiling of what you can achieve this way.

                                                          > Nope. You only need a class definition.

                                                          How hard is it to understand that to get a class definition, all the stuff that's used inside the class, including declarations of internals like private fields and methods, needs to be included first? How hard is it? It seems like you are terminally unable to see it. Have you never touched a seemingly unimportant header file and had to rebuild 80% of your project? Because that's the common case in most real world C++ projects (and also some badly designed C projects btw.), in my experience.

                                                          > Now it's not about build times? I thought it was and you had said that all along? Now the story changes again.

                                                          Are you insane, you first critized me for making too many different points, then later you claimed I had NEVER talked about build times, which I refuted with a simple Ctrl+F argument. Then later you critized me for talking ONLY about build times. Now you critize me again for talking about a variety of things?

                                                          While I have stressed from the beginning that I'm talking about systemic problems, which manifest in lots of ways. Maybe Ctrl+F for "and here are a million examples why" for example?

                                                          You are a weasel with no purpose other than talking down on me, and you haven't made a single interesting argument. Get lost.

                                                          > All 6MB of sqlite compiles in a single second

                                                          Sure, a while ago, I even compiled it in 300ms using tcc (as a test). Do you know why that works? Because sqlite is written in C, without insane C++ classes and features. They compile everything as a single file (like raddebugger does too btw., a legitimate approach but I'm not saying this is the solution for everyone), circumventing the quadratic translation unit scaling problem.

                                                          > You added one already. PIMPL is the same as your indirection from heap allocating a predeclared struct so that you can return it from your constructor. The price is heap allocation and indirection.

                                                          A PIMPL object is one that is referenced as a pointer (of void-type or forward declared type) in a struct trying to protect implementation details and dependencies, because C++ doesn't exactly want you to do that.

                                                          The price of an actual C++ PIMPL object is that you'll go insane duplicating all the methods and writing all the call forwards.

                                                          This is NOTHING like a forward declared C struct, which is the exact opposite. There is NO duplication and call forwarding. You haven't got a clue what you're talking about.

                                                          A forward declared C struct does not add another level of indirection. You can't put the object itself directly on the stack unless you know the struct definition, that is obvious. It's the price to pay for true abstraction, abstracting from the internals of the object and treating it uniformly as a pointer value. But that's not a problem at all, since you would never want to put abstracted objects on the stack. Putting objects on the stack is how you write tiny scripty toy applications. In systems programming, object lifetimes don't correlate to function call lifetimes, so you cannot put objects on the stack. If you are able to put most of your objects on the stack by value, you are working on a toy app.

                                                          Contrast objects here with plain structs, for example struct Float3 { float x, y, z; }. Of course you expose those as values, these are stateless objects. And putting them on the stack is fine. That has nothing to do with PIMPL or implementation hiding AT ALL.

                                                          > With your API you created an object with none of the huge advantages of being able to treat it like every other value in modern C++.

                                                          There is no "like every other value" in C++, regardless of how hard people are trying, and regardless of how much complexity these people pile on top of this language.

                                                          The only successful "every other value" is plain data, which you can simply copy as bytes. I could queue a lecture now why Unix was successful with its file concept of "raw bag of bytes", but I'm done with you. Good bye.

                                                          • CyberDildonics 16 days ago

                                                            you don't understand what you're talking about Are you insane, You are a weasel Get lost.

                                                            Lots of insults, but the difference here is that I know exactly how to do what you're doing in C, but it doesn't seem like you ever tried out modern C++.

                                                            How hard is it to understand that to get a class definition, all the stuff that's used inside the class, including declarations of internals like private fields and methods, needs to be included first? How hard is it?

                                                            This is a matter of dependencies and if your dependencies are simple definitions too it isn't going to matter. You are going to have to have definitions of your structs and functions in C too. A data structure without dependencies in C++ is no different than a data structure without dependencies in C. This isn't a language issue and has nothing to do with destructors.

                                                            without insane C++ classes and features.

                                                            It isn't destructors that cause long build times, if it was you could prove it. I said this multiple times but you're mixing a bunch of stuff together because you know staying on topic doesn't match what you're upset about.

                                                            I'm talking about systemic problems, which manifest in lots of ways

                                                            You didn't give any explanation of these, you just made a lot of claims. You still seem to think claiming something with no explanation is evidence. A kid saying they run fast over and over doesn't prove anything, you have to show it.

                                                            You haven't got a clue what you're talking about.

                                                            They are both forward declarations which I avoid like the plague for all the reasons I outlined before. Your whole schtick is that you want forward declarations and don't care about all the ownership and value semantics that save you from 50 years of C bugs.

                                                            There is no "like every other value" in C++, regardless of how hard people are trying, and regardless of how much complexity these people pile on top of this language.

                                                            Another claim without evidence. Make a value, it goes out of scope. Make an 'object' data structure, it goes out of scope. Move it if you need to, so simple!

                                                            which you can simply copy as bytes.

                                                            Copy constructors do this if you need them to. You can't just use plain structs with static sized arrays for everything, at some point you need to make real data structures that use the heap and then you will need to manage their memory. It could be automated for you but you might have to be a little more open minded.

                                                            • jstimpfle 16 days ago

                                                              You are continuing to fight strawmans I have never said and continuing to not get what I said and continuing to lecture me about beginner level C++. I am bored.

                                                              > Move it if you need to, so simple!

                                                              Move it, so simple, pointer invalidation.

                                                              Have you thought about... not moving it? So simple! "I need to move the outermost layer of a complicated structure, because I'm too stubborn to have just put this structure on the heap in the first place -- with nodes that link to it, and I'm not sure if other structure point to it... but anyway I NEED to move it, and I'm happy to implement all silly move and copy constructures and conform to this rigid ruleset even though there is no point in 90% of the cases, and that will lead to incredibly hard to diagnose bugs", said... no competent systems programmer ever.

                                                              Have you considered why C++ is like a pile on top of a pile of fixes, exceptions, copy semantics, move semantics, rvalue references... That is the polar opposite of simple.

                                                              Obviously you have not. But if you want to know, the reason why is that they are trying to treat things as values that are not values but stateful objects. They are trying to make a toolbox of hacks to treat everything the same. It does not work. It is a beginner level cardinal sin.

                                                              > at some point you need to make real data structures that use the heap

                                                              Do you remember when you were arguing that you want to avoid putting things on the heap because performance, and I said allocating things on the stack is for toy programs, like.. in my last post from 1 hour ago? I think you must have forgotten. Now you're claiming you want to allocate on the heap and I am not doing real datastructures on the heap???

                                                              Please give up. It is embarassing.

                                                              Or better, please go read any C++ codebase with templates and classes and copy semantics and move semantics. Get more brain damage as a result. And please leave me alone.

                                                              • CyberDildonics 16 days ago

                                                                Move it, so simple, pointer invalidation.

                                                                It works for everyone else, I'm not sure why this is controversial.

                                                                You are continuing to fight strawmans

                                                                Like bringing up PIMPL for no reason?

                                                                Have you thought about... not moving it?

                                                                No, because I want to have ownership semantics and be able to return data structures from functions while having clear ownership that is part of the program and not knowledge that has to be gleamed from source code or learning from crashes.

                                                                Have you considered why C++ is like a pile on top of a pile of fixes, exceptions, copy semantics, move semantics, rvalue references... That is the polar opposite of simple.

                                                                Which one is the argument against destructors? The simplest thing in the world. Copying and moving are solutions to problems you already demonstrated, you just don't want to admit that you and everyone else has them.

                                                                Now you're claiming you want to allocate on the heap and I am not doing real datastructures on the heap??? Please give up. It is embarassing.

                                                                It's interesting to claim (without evidence) that I don't know what I'm talking about while saying stuff like this. If you follow what I said before the fact is that with your forward declarations you are putting the structs on the heap so that they become globals and can outlive the constructors. Then whatever fields they contain are going to be pointers to the heap for the actual data of the data structure. When you want that data you have to dereference the pointer to the struct, then dereference the pointer to whatever arrays you are using. This is double indirection. It is more allocations, more memory frees, more pointer dereferencing (all of which are slow) and not necessary. In C++ with value semantics that first struct would be on the stack and gets moved or elided out of the function that creates it. You can't do this with forward declaration because you don't know the size yet.

                                                                Or better, please go read any C++ codebase with templates and classes and copy semantics and move semantics. Get more brain damage as a result.

                                                                How many did you read?

                                                                And please leave me alone.

                                                                You don't get to fling a bunch of insults then tell someone to leave you alone. I know you want it both ways but that isn't how it works.

                                                                • jstimpfle 16 days ago

                                                                  >> Move it, so simple, pointer invalidation.

                                                                  > It works for everyone else, I'm not sure why this is controversial.

                                                                  Show the evidence. It does not. It introduces vast amounts of complexity. So much that they were thinking they had to extend the syntax. Great, from rule of 3 to 7, from 41 ways to blow your leg off to 118 ways.

                                                                  I'm betting it means you can easily google LOTS of memory bugs stemming from this complexity. It "just works" for everyone else, until it does not, and then nobody understands what's wrong because they created a complexity monster.

                                                                  And what do you think how many intended "moves" get silently converted into copies because some failure to properly forward rvalue references and similar?

                                                                  • CyberDildonics 16 days ago

                                                                    Show the evidence. It does not. It introduces vast amounts of complexity.

                                                                    The evidence is that everyone could do what you showed and they don't, they do this instead. In my experience memory ownership bugs are almost non-existent, an entire class of problems is wiped out.

                                                                    It's clear that since you're asking about this stuff you haven't actually gone down this road yourself, which means that you're railing against something you don't understand out of fear of something different.

                                                                      #include <vector>
                                                                    
                                                                      using namespace std;
                                                                    
                                                                      vector<int> makeVec() {
                                                                        vector<int> v{1,2,3};
                                                                        return move(v);
                                                                      }
                                                                    
                                                                      int main() {
                                                                        auto  a = makeVec();
                                                                        return 0;
                                                                      }
                                                                    
                                                                    Not difficult or complex. In this case you have something that isn't a constructor returning a data structure that contains heap allocation. You don't have to guess at ownership or dig through documentation (if it exists).

                                                                    Keep an open mind, there's a reason people consider old C style archaic.

                                                                    • jstimpfle 16 days ago

                                                                      I was not asking, and certainly not for a toy example, are you STILL under the impression you need to explain beginner level C++ to me? You can btw remove the move() from the return statement in this example. It's normal to omit it as it is implicit and specifying it does not make a difference. Did I mention that move semantics introduce a ton of complexity and make it non obvious what is happening?

                                                                      > Keep an open mind, there's a reason people consider old C style archaic.

                                                                      It is superficially a little bit archaic but it's not as bad or cumbersome as people make it, like baking a good bread from old grains in a modern oven. The point is if you focus on superficialities and micro optimize everything, you will make a mess and get what you deserve (i.e. modern C++).

                                                                      The result from baking with simple ingredients is better tasting and healthier than a modern factory bread.

                                                                      What people consider archaic or in particular insufficient is a function of their knowledge and experience. Check out the raddebugger code and the many excellent explanatory videos about the design of the codebase. You will learn a lot and you might change your mind about many of your mainstream positions.

                                                                      • CyberDildonics 12 days ago

                                                                        are you STILL under the impression you need to explain beginner level C++ to me?

                                                                        Yes

                                                                        you can btw remove the move() from the return statement in this example.

                                                                        First you say you have a problem with not knowing if something will copy or move, now you have a problem with an explicit move to rely on copy elision.

                                                                        Seems like you just want to complain about problems that don't exist.

                                                                        This is why I think it's necessary to explain the basics.

                                                                        function of their knowledge and experience

                                                                        Now we are to the "get good" part of the C true believe argument. People have been trying to get good for 50 years and all the same bugs still happen.

                                                                        You will learn a lot and you might change your mind about many of your mainstream positions.

                                                                        I've already been on both sides of this argument. I like data structures, value semantics and avoiding double indirection.

                                                                        Check out the raddebugger code

                                                                        Check out the code to every other piece of software you use.

                                                                • jstimpfle 16 days ago

                                                                  > Like bringing up PIMPL for no reason?

                                                                  What disorder are you suffering from? Please check who was bringing up PIMPL. Hint: it was the person who does not know what they're talking about.

                                                                  > Which one is the argument against destructors?

                                                                  oh. my. god. THE COMPLEXITY. The systemic issues.

                                                                  > Copying and moving are solutions to problems you already demonstrated

                                                                  Which? I presented my solution to the move problem, it was: just don't move. And for copying: it's very context dependent what "copy" should even mean. There is no point in general in making a single function.

                                                                  This whole semantics infrastructure is all just there to allow generic template code, which results mostly in: very bad, bloated, and slow code that is full of forgotten edge cases. For example, to take a very popular example, std::sort. you can sort a vector of vectors, it would then use move semantics to swap elements. Fine: I would just sort pointers instead or come up with an ad-hoc solution that is way faster anyway. (other than the fact that general purpose sorting of longer chunks is quite rare in systems programming).

                                                                  > This is double indirection. It is more allocations, more memory frees, more pointer dereferencing (all of which are slow) and not necessary.

                                                                  My friend, you don't understand the first thing about how computers perform their work, let alone how you have to balance these concerns with software architectural concerns. You could convert all the std::vectors in your programs and access them using pointers, in most cases you probably wouldn't notice the tiniest bit of a performance difference.

                                                                  But the reason why C++ likes to embed "objects" as values (even though that's almost invariably bad from an architectural standpoint) is almost entirely unrelated to performance (with the caveat that embedding might save you a couple heap allocs and frees, but for real stateful objects & data structures, that isn't a good reason to embed). Of course you shouldn't add any indirection for objects that aren't really objects but merely a scope-exit, like lock_guard for example.

                                                                  The primary reason is because it painted itself into that corner. It's syntax & semantics. You wouldn't "profit" from RAII if you added pointer indirection to your objects. (To fix that, later std::unique_ptr<T> was popularized, which again is an embedded struct but contains only a pointer -- which in typical C++ manner introduced its own additional horrors).

                                                                  Another reason why C++ wants to embed objects is that its operators (like operator[], operator+ etc.) are defined on "value" type syntax expressions. Well it's basically the same reason as above RAII argument, since that argument is about the destructor-"operator". You cannot call methods & operators on pointers. You cannot do `std::vector<Foo> *ptr = ...; do_foo(ptr[i]);`. Get it? The best you could do would be `do_foo(ptr->at(i))` but it's not the same. Part of the reason why C++ calls methods on value type expressions is of course C compatibility, C++ can't afford to mess with pointer syntax and arithmetic.

                                                                  I'm sorry. C++ is broken.

                                                                  > How many did you read?

                                                                  Way too many.

                                                                  • CyberDildonics 16 days ago

                                                                    oh. my. god. THE COMPLEXITY. The systemic issues.

                                                                    I'm hearing it, I'm not seeing it. Repeating the same thing isn't evidence.

                                                                    My friend, you don't understand the first thing about how computers perform their work, let alone how you have to balance these concerns with software architectural concerns.

                                                                    Seems like projection when you're fine with double memory allocations and double indirection. Again you can make these bold statements but saying pointer chasing has no performance impact is what people say when they don't understand the cost of TLB misses and caches misses.

                                                                    C++ likes to embed "objects" as values

                                                                    "C++" doesn't like to do anything. It has things in the language like destructors that basically no one has ever been against until now.

                                                                    You wouldn't "profit" from RAII

                                                                    I don't know what this means but people using features a certain way doesn't have anything to do with destructors. That's the definition of a straw man fallacy.

                                                                    It's like your C program doing double indirection. You can't blame C for that (unless you want to try to say that not defining your structs is a good idea).

                                                                    You cannot call methods & operators on pointers. You cannot do `std::vector<Foo> ptr = ...; do_foo(ptr[i]);`. Get it?*

                                                                    Yes you can, an operator is just a function, get it?. You don't need to because you can use things as values and not fragile pointers that have to have their ownership semantics memorized for every individual data structure and function (interesting that you never addressed this). You don't get operators in C, so it's bold to be wrong and about a feature you are somehow denigrating.

                                                                    Also one separate function being different than the operator is not a language level feature, it is how that one library data structure is made.

                                                                    I'm sorry. C++ is broken.

                                                                    Based on you misunderstanding it because youtubers steered you wrong?

                                                                    All I was arguing was that destructors are good and you are having a massive reaction to that that seems to include every misguided frustration with the whole language you can think of.

                                                                    > How many did you read?

                                                                    Way too many.

                                                                    And you said it causes brain damage?

                                                                    • jstimpfle 16 days ago

                                                                      > Again you can make these bold statements but saying pointer chasing has no performance impact is what people say when they don't understand the cost of TLB misses and caches misses.

                                                                      You are right to call this out but I did not mean to imply that it would not increase load on the cache at all. The most important optimization is keeping data structures simple, flat, and coherent. Making many micro optimizations can backfire because it reduces clarity and flexibility. I should not argue that vector metadata block should not be embedded as value in a struct, but move semantics is where it is getting silly, complicated, and we are losing control of program behaviour.

                                                                      For example, with your cache concerns, don't forget to group data by access patterns and write patterns. Not doing so may hurt the cache more than an indirection. If you blindly embed everything by value religiously, you deserve neither flexibility nor correctness nor performance.

                                                                      > Yes you can, an operator is just a function, get it?

                                                                      An operator is just a function but with different syntax. You can not do my example, that snippet does not do the intended job. Get it?

                                                                      > (unless you want to try to say that not defining your structs is a good idea).

                                                                      It is a good idea when it's about architecture. It is right to embed small and in particular stateless structs directly, but otherwise adding one level of indirection is often absolutely the right call.

                                                                      > All I was arguing was that destructors are good

                                                                      All I'm saying is that destructors, while they may seem convenient, are way overrated and the systemic issues caused by reliance on C++ classes and class features (including destructors) are still not well enough understood by the mainstream in 2026.

                                                                      • CyberDildonics 12 days ago

                                                                        If you blindly embed everything by value religiously, you deserve neither flexibility nor correctness nor performance.

                                                                        I don't know what 'deserve' is supposed to mean, but I just showed how to get all three.

                                                                        don't forget to group data by access patterns and write patterns

                                                                        Values on the stack are going to be grouped together and they are going to be in cache.

                                                                        You realize using two heap allocations means twice the frees, twice the heap contention from multiple threads and chasing through two pointers for every data structure access right? In what universe does this work better than a single pointer lookup?

                                                                        Making many micro optimizations can backfire

                                                                        This is an even more handwavey than usual.

                                                                        All I'm saying is that destructors, while they may seem convenient, are way overrated and the systemic issues caused by reliance on C++ classes and class features (including destructors) are still not well enough understood by the mainstream in 2026.

                                                                        You can say that but you have given zero evidence of any of this. It took you a very long time to even get to your claim, maybe now you can start to back it up.

                                                                        Meanwhile I gave extensive evidence based on your own examples of how the same bugs have happened over the last 50 years and double indirection and vague ownership cause problems on small and large levels.

                                                                        • jstimpfle 7 days ago

                                                                          You don't understand even the first things of what I say. That's because you apply beginner level concepts and understand to argue, and are not looking for nuance or deeper understanding at all.

                                                                    • jstimpfle 15 days ago

                                                                      > Also one separate function being different than the operator is not a language level feature, it is how that one library data structure is made.

                                                                      That's not so much the point: the point is that even when calling a regular method conveniently as ptr->methodname(), you are calling the method name not on a pointer expression but on a value expression. ptr->methodname() is effectively (*ptr).methodname().

                                                                      • CyberDildonics 12 days ago

                                                                        That's not so much the point:

                                                                        It is the point since you compared two things that have different uses, then said you can't call an operator on a pointer, which is wrong.

                                                                        • jstimpfle 7 days ago

                                                                          You don't get it. That's because you still don't understand some basic things about the language. There is no method call here on a pointer expression. There is only a call on a value expression.

        • kasumispencer2 18 days ago

          "Aggressive arrogant dismissal of anything except their exact view"

          Man, if only someone around here had even if just an inch of self-awareness...

      • tialaramex 19 days ago

        Casey spends a lot of effort on what he considers an anti-pattern where you're making a huge number of separate objects. I think a lot of this comes from Java, a language where all the user defined types actually are obliged to be heap allocations. If I make a Goose type, and I say I want a Goose, Java will allocate space on the heap for the Goose and put my Goose there, that's really how Java works. If I make a growable array of them ArrayList<Goose>, and add each of 500 geese, that's 500 allocations for geese plus maybe 8 allocations for the ArrayList, so 508 total. Ouch. If making a Goose was itself cheap this overhead hurts badly.

        But a lot of languages aren't like that, and so this doesn't translate. Obviously in Rust with Vec<Goose> that's only 8 allocations, each local Goose lives in the stack - or, if you knew up front there were 500 geese, you Vec::with_capacity(500) and it's a single allocation - but similar is true in many languages, Java is an outlier.

        • gf000 19 days ago

          Java doesn't mandate the usage of a heap - it can in certain cases avoid doing so and allocate on the stack (escape analysis).

          Besides, as mentioned java's allocations are much closer to something like using an arena in a low-level language, then a "slow" malloc. It uses thread-local allocation buffers, where you have a large buffer with a pointer pointing to the start of the free region. Allocation is just a pointer bump, not even needing synchronization since it is per a single thread. As it gets full, the GC moves out still alive objects in the background and resets the buffer.

          This is pretty much the most efficient one can be after per-object type arenas and simply not allocating.

          • tialaramex 19 days ago

            You're correct that by an "as if" rule the JIT may in some cases be able to do this trick, but the specification says you're getting a heap allocation and so in most cases, including the example I gave that's exactly what happens.

            It doesn't matter that you say this is "much closer to something like using an arena". It's definitely work that we needn't do at all and that's AFAICT that's how Casey ends up over-correcting so badly.

            > This is pretty much the most efficient one can be after per-object type arenas and simply not allocating.

            Sure. "A C is pretty much the highest grade one can get in this class, after grades A and B".

            • gf000 19 days ago

              What "work" do we do needlessly? It's a pointer bump. With reclamation being no work. Comparatively a malloc call will have to do extra work to defragment.

              Also, a stack is not a separate hardware element of the RAM, it's not faster than a sufficiently hot part of the heap - it just so happens that the current stack frame is pretty likely to be in cache.

              • tialaramex 19 days ago

                > What "work" do we do needlessly? It's a pointer bump

                Any work here was needless. There was no need to do work.

                • gf000 18 days ago

                  On the allocation happy path there is literally less work in case of Java. Like at least try to get what I'm saying and argue with that - I'm not saying that Java is faster or whatever, but that it has chosen different tradeoffs, and "stack vs heap" is an oversimplified model that doesn't help us understand the real performance impacts.

                  A pointer bump is a pointer bump, vs a malloc call that will try to find place, do some housekeeping, etc. And your Vec will need at least a single allocation, the backing buffer is not on the stack.

                  • tialaramex 18 days ago

                    > On the allocation happy path there is literally less work in case of Java

                    Doing more allocations isn't "less work". No matter how many times you mumble "But it's just a pointer bump" the alternative was no work.

                    > it has chosen different tradeoffs

                    Sure, it's easier to implement this, the New Jersey style. But that's not a benefit to anybody else, so if you're not Sun Microsystems (which you aren't, Sun no longer exists) then that's not actually a benefit at all and this was a bad trade.

                    Which is why people have expended an eyewatering amount of effort on Project Valhalla to some day fix this stuff.

        • ahtihn 19 days ago

          Maybe I'm missing something but when would the 500 geese instances ever be stack allocated in Rust? That comparison seems unfair, the lifetime of that kind of object isn't going to be compatible with stack allocation.

          Allocations are really really cheap in Java by the way, so I don't get how 500 allocations would even be an issue.

          • tialaramex 19 days ago

            When you make a local variable with a Goose in Java, that's a heap allocation

                Goose jim = make_a_goose_somehow();  // Java, so jim is on the Heap, no way around it
            
            When you make that variable in Rust...

                let jim : Goose = make_a_goose_somehow();  // Rust, jim is on the stack
            
            Now, if we make a bunch of geese, maybe in a loop, and we put them into our growable array type...

                ArrayList<Goose> geese = new ArrayList<Goose>();
                // ... some loop eventually
                  Goose a_goose = somehow_get_this_goose();   // That's an allocation
                  geese.add(a_goose);
            
            
            But in Rust...

                let geese: Vec<Goose> = Vec::new();
                // ... some loop eventually
                  let a_goose : Goose = somehow_get_this_goose(); // But this is not
                  geese.push(a_goose);
            • gf000 19 days ago

              Memory is memory, stack is not a unique hardware element. It just tends to be hot, but so can certain part of "the heap".

              Of course this is a toy example, but were the compiler not smart enough (it is surely smart enough in this case) then the "too simple rust" version may actually be slower - it would allocate a Vec on the stack, but only a length, capacity and a pointer is stored there, the actual backing array is on the heap. Then it would create stuff on the stack, and copy over those bytes to the heap, object by object (it's a move).

              Meanwhile the java version would have a continuous region of memory, next to it it would have objects, and it would just write pointers to said objects without moving/copying anything.

              Surely enough rust is smart enough to optimize out this useless move in this case, but I think you are painting a way too simplified picture here.

              • kibwen 19 days ago

                What tialaramex is saying is that, in the Java code, there will be a separate allocation for every `a_goose` that gets added to the ArrayList, whereas the Rust code only has a single allocation for the backing storage for the Vec (not counting the resizes that occur as the ArrayList/Vec grows (both cases have ways to preallocate the proper size to avoid any resizes)). The context of this subthread is just to explain why someone who has Java experience might be prone to overcorrection when it comes to avoiding heap allocations.

                • gf000 17 days ago

                  But one is a "malloc allocation" and the other is a special "java allocation".

                  The two are apples and oranges and it makes no sense to compare them -- the latter is severalfold cheaper. Of course this comes at a price (read/write barriers, complex runtime, etc).

                  > The context of this subthread is just to explain why someone who has Java experience might be prone to overcorrection when it comes to avoiding heap allocations

                  That's what I don't really understand: if anything, someone with Java experience should be prone to avoid heap allocation in something like Rust as it is more expensive on almost every other platform. This is what I'm talking about, and apparently I wasn't clear.

            • torginus 19 days ago

              This isn't necessarily true - at least not in a meaningful way - if Goose has a Vec in it, that'll end up on the heap no matter what.

              • tialaramex 19 days ago

                (Sigh)

                Fine. If we put a growable array type inside Goose the backing store for such a type would [if needed] live on the heap, unfortunately in Java we're not allowed to use a primitive type like the signed integer here, so lets put a growable array of Doodads where each Doodad is 64 bits.

                So now each Java Goose has an ArrayList<Doodad> and yup, each Doodad goes on the heap, and then the ArrayList's backing store goes on the heap with pointers to the Doodads, and then the rest of the Goose goes on the heap too.

                In Rust we skip most of those steps for Vec<Doodad> but if there's at least one Doodad we do need to actually have the backing store, the Doodads live directly in that backing store.

                Of course if there aren't any Doodads, Java still pays to make the backing store anyway, that's just how Java works again. Rust doesn't do that, an empty Vec<Doodad> is just a dangling pointer, zero capacity, zero length. Since the length and capacity are zero we'll never dereference the pointer.

                The story doesn't get better for Java if you make it more convoluted, that's not how any of this works.

                • torginus 19 days ago

                  To be clear I am not picking nits, nor am I trying to prove that 'language X' is better than Rust - but if you want to mention stack allocation as an advantage, then it has to be general enough to work all the time - in my sibling comment I mentioned arenas, which fix this issue. If you malloc in a function-local arena, both the Goose and the Vec inside it end up in there, and will be automatically freed on return.

        • torginus 19 days ago

          Actually, this is my personal opinion, but in Java, allocating an object is just bumping a pointer, so it's much cheaper than doing a malloc in C. I personally don't think the stack is a good place to put temp values and I'm sure neither does Jon Blow, considering he put temporary arena backed allocators right in the language.

          • tialaramex 19 days ago

            Having an arena allocator is completely unrelated. It's one of the features all of these languages out of the Handmade Community seem to have, including Odin (the subject of this thread) and Zig. It's not useless but it's a weird niche to target first.

            Local variables don't somehow live in this arena allocator in Odin or Zig, and presumably (I haven't used it) not in Jai either. The obvious place for a local to live is the stack - unless you're Java and you need all your user defined types to live on the heap so that they have unique identities. So that's where locals live in Rust, Zig, Odin, C, C#, Go ...

    • pseudony 19 days ago

      Games ? Many have talked about it, but many also make their games work inside of Unity and so on, so, depends on the project.

      My angle is systems programming, and there, it absolutely matter. If you are performance sensitive, then you try to avoid crossing the user-space -> kernel boundary more than you have to.

      Eg, ask for lots of memory, manage with arenas.

      Interestingly Odin and Zig both lean into this heavily. Rust went a different route but has tried later to bolt on pluggable allocators.

      • cmrdporcupine 19 days ago

        Rust barely even trying on the pluggable allocators (seems like it's never going to land, afaik "allocator-api" has been sitting proposed in nightly only since 2018) is one of the things that frustrates me (fulltime Rust eng) about the language and makes me feel like it's just a language that's been eaten by web services developers, applications level work, and/or tokio, and isn't "serious" as a systems PL really despite the verbiage.

        Building a database, operating system, etc. absolutely requires fine tuned control over allocation. You can get around some of these things in Rust, but it will fight you. You'll effectively have to turn your back on the containers in std and build your own vectors, maybe even your own Box, etc.

        Odin looks really appealing to me at one level, but I'd have a hard time switching to any language at this point that doesn't have a borrow checker story.

      • kibwen 19 days ago

        > My angle is systems programming, and there, it absolutely matter. If you are performance sensitive, then you try to avoid crossing the user-space -> kernel boundary more than you have to. Eg, ask for lots of memory, manage with arenas.

        This gives the misleading impression that ordinary memory allocators are materially different from arena allocators. They aren't. Both types of allocators first ask for a big block of memory from the kernel, then dole that memory out in userspace. There's no need to cross the userspace/kernel boundary more often than you need to, especially when you consider that you can replace the standard platform allocator with whatever you want.

        To wit, C doesn't emphasize arena allocation anywhere near as much as Zig et al do, and yet nobody alleges that C is somehow less suitable for systems programming than these languages. Have you considered why that is? Because, for the most part, arena allocation doesn't make a significant difference, and in the places where it actually does make a difference, you can trivially build an arena allocator on top of the standard allocator.

        • wasmperson 19 days ago

          Agreed. IME the main reason to choose arena allocators is for correctness, not speed. They make similar time/space tradeoffs to garbage collectors in that they grant higher allocation throughput in exchange for more memory usage.

          The perf argument against RAII is very abstract and is less "RAII causes bad performance" and more "the kind of design that leads you to reach for RAII is the kind of design that's bad for performance." There exist similar hand-wavy arguments against many other C++/Rust features.

          More generally, "you shouldn't even want that" is basically a meme at this point in programming language design. Every new-ish language has some version of it.

          • jstimpfle 18 days ago

            > the main reason to choose arena allocators is for correctness, not speed. They make similar time/space tradeoffs to garbage collectors in that they grant higher allocation throughput in exchange for more memory usage.

            I'm not quite sure, do you mean arenas are slower, and use more memory, compared to standard vector-style allocation (which does a lot of copying, iterator invalidation, and wastes like 0.25x memory on the average), or compared to individual malloc/free (which does a lot of book-keeping work and wastes book-keeping memory)?

            • kibwen 18 days ago

              The difference between an arena allocator and RAII deallocation is that the latter is eager. This is the whole point: the problem that an arena allocator attempts to solve is to presume that fine-grained freeing is slow and thereby solve that by batch-deallocating a whole lot of things at once. But it will, be definition, end up using at least as much memory as an eager deallocation scheme, because the whole point is to not be eager, which means not immediately freeing memory even when you could. This is a fundamental tradeoff. I'm not sure what you mean by "vector-style allocation", but iterator invalidation et al is a non-sequitur for this discussion.

              • jstimpfle 18 days ago

                Iterator invalidation is absolutely a huge deal for many datastructures in practice. From an ergonomic standpoint alone it makes a huge difference. 10 years ago I argued the opposite, but juggling indices simply is not fun. Replacing pointers with indices can be useful but it's not a good default.

                You are also ignoring bookkeeping overhead and fragmentation that comes with individual allocation.

                The important difference between arenas and RAII as far as I'm concerned is that the former allows exploitation of allocation patterns, like stack shaped allocations, which can reduce complexity in a meaningful way, requiring no cleanup code at all. RAII on the other hand does not give you that -- it is just a disciplined system to automate some code, but the complexity is still fully there, and a lot of constraints are put on the types and your internal organization in order for RAII to work.

                Arenas are quite a good fit for frame memory in graphics programming, and they do not waste memory there if done right. On the contrary they probably save some, but that's not the point here. We're typically talking about a couple megs per frame at most, which is spare change.

                Some people, like Ryan, have managed to apply arenas more widely, but personally I am more in favour of a varied mix, and don't mind a bunch of manual code either, but I definitely like to control allocation more closely compared to what e.g. malloc/free allow. I like to keep objects in their specific subsystems. I have written my own block allocator to do this. Now allocation does not show up anymore on my profile almost at all, it's <<< 1÷ of my CPU usage even though I recreate tens of thousands of objects per second. Also syscalls are ~zero as long as memory usage is roughly the same from frame to frame.

                As I said elsewhere, performance and correctness/clean modelling always go hand in hand. The correct model must allow for the right level of performance, or else it's not the correct model.

          • jstimpfle 19 days ago

            Correctness (the kind that comes from simplicity and maintainability) and performance pretty much always go hand in hand. The only additional ingredient to "bridge the gap" between the two is detail.

        • pseudony 19 days ago

          Look up a few comments, I do systems programming. I am aware, you are barking up the wrong tree, friend.

          That said. You asked about C, which I use for my job. Most every large C code base end up abandoning the stdlib (such as it is) and inventing their own. Since they do, we aren’t as hurt by abandoning it as you would be in e.g. Rust - the rust stdlib is useful, the C stdlib is.. not great.

          Once you abandon the stdlib, a likely first stop is writing your own routines for allocating and freeing memory. There are different approaches here, from glib’s or sqlite’s alloc and free routines to people writing an allocator abstraction (basically a struct with a vtable for allocating/realloc/free) and when you build your own “stdlib” around this abstraction, you are fine.

          As for why you may want arenas vs other allocation strategies, that again deals with how often you are comfortable going across the user-space/kernel boundary and how clever you can be with your allocations or how much internal fragmentation you can accept.

          As with all other stuff, it depends. But arenas are often great when you can assert that a series of objects share the same lifetime (death time, rather). In these cases, your amortize the syscall cost, have nearly no additional work to manage the memory (contrast to e.g. the complexity of jemalloc) and can free a series of objects in constant time.

    • moron4hire 19 days ago

      Yeah, that's weird. I first learned about RAII from professional game developers at gamedev.net.

  • hkalbasi 19 days ago

    If the major obstacle for adopting Rust is C interop, you may find my project CO2[1] appealing. It helps you to define C crates, `#include` C headers, while exporting a Rust API with Rust types in your crate boundary.

    [1]: https://github.com/hkalbasi/co2

andyfilms1 19 days ago

I've been using Odin for about 6 months now, and to be honest, it's hard to find fault with it. I've used it for STM32 microcontroller firmware, web and desktop applications, and all are performant and compile quickly.

My one issue is (and I'm fully aware it will never happen) I do wish there was some sort of first-class solution to inheritance. I've grown to love procedural programming, but some problems really are just better solved with a more OOP approach. Just because classes exist does not mean they need to be used.

But as far as a language to "get stuff done" with as few tradeoffs as possible, Odin is about as good as I can imagine a language being.

  • RetroTechie 19 days ago

    Out of curiosity:

    In your opinion, could a minimal system to develop in Odin be squeezed into a device like the one(s) you targeted?

    That's assuming maybe some tweaks to the toolset, doing without some niceties, but not cutting core features out of the language.

    Asking 'cause I have a passing interest in programming languages that allow for native development on really small implementations (think sub-1MB on bare metal). The list of candidates doesn't seem long.

    • andyfilms1 19 days ago

      Odin is not like JS or something where you'd need a VM or transpilation process to target an embedded system. It's just C with nicer syntax and modern data structures, there's no "squeezing" required. You just compile for the target you want to run on.

      Here's a UI framework, if you scroll down you'll see it on a Raspi Pico: https://github.com/MadlyFX/Ansuz

      • RetroTechie 19 days ago

        I think you missed "native development". I'll rephrase:

        Could a toolset to develop in Odin be made to run on (not just target) an STM32 microcontroller like you used?

        > It's just C with nicer syntax and modern data structures

        That suggests the above would (in theory) be possible for any device that's roughly in the same class as "can run a C compiler". Correct?

        • fatty_patty89 19 days ago

          > It's just C with nicer syntax and modern data structures

          it's not, it's llvm

        • gingerBill 19 days ago

          > STM32 microcontroller

          The answer is "yes" depending on what you mean by STM32 :D

          But if it's one we don't currently support officially, it should be pretty easy to support too, with probably a little extra assembly.

  • clumsysmurf 19 days ago

    I'd like to hear more about Odin + STM32 MCU firmware, do you have any good resources? I'm also curious how difficult it may be to using it with ESP32 (ESP-IDF) / RP2350.

  • christophilus 19 days ago

    I’d be interested in reading about your experience building web applications with it. Last I looked, its stdlib didn’t have great support for that.

  • pjmlp 18 days ago

    Personally, I have a certain Turbo Pascal feeling while playing around with it, yep I am aware of the influences.

Razengan 19 days ago

This was a pretty funny video for a language launch:

https://www.youtube.com/watch?v=dLPAqXi9In0

gcanyon 19 days ago

I wonder if this will help them get a wikipedia page. (not sure whether this comment is a joke or serious...)

  • leecommamichael 19 days ago

    It would, but the book has existed for a while now, which is a good thing for anyone looking to learn Odin. The author, Karl, has had time to polish and update the text. He has his own Discord and is also available in the Odin Discord and makes helpful posts there as well.

ant6n 19 days ago

Kinda wanna know why I should learn this language. Unfortunately there’s no wiki entry (deleted with some controversy abut notability), so it’s hard to get the gist of it.

  • kulkalkul 19 days ago

    Odin overview is great resource for getting a quick gist (and learning the language as a bonus): https://odin-lang.org/docs/overview/

    But mainly, language doesn't have a special gimmick. The main idea (imo) is it is opinionated to have defaults to cater for majority of the cases. So once you get used to it, it is pleasure to write C-like code in it.

WalterBright 19 days ago

Oooodiiinn!

https://youtu.be/ZqJHqXERslM?t=59

datakan 19 days ago

I wonder when we'll see new languages created specifically with LLM's in mind.

  • lioeters 19 days ago

    I think it would be better to approach it from the other side, the priority is not to design a language for LLMs but a language more suitable for humans to think with. And not a natural language like English, which is inconsistent and allows illogical formulations, but something like Esperanto or Interlingua (Latino sine flexione). Something that is based on mathematics and logic at the bottom, like Lean, with enough abstraction layers for a person to be able to "speak" with the machine intuitively.

  • pjmlp 18 days ago

    The way forward will be more focused on formal specifications kind of approach, and there are already a few attempts at it.

  • leecommamichael 19 days ago

    We’ve seen several already, just search it.

  • xqb64 19 days ago

    What would that look like?

    • moron4hire 19 days ago

      An LLM-only oriented language doesn't make sense, because without human generated training data there is nothing for the model to learn from.

      But if a human-oriented language were to be designed to also be better for LLMs, I think it would involve deeply expressive syntax that can succinctly but distinctly represent a very broad set of common operations. Succinct so context can be managed well, distinct so completions don't confuse one thing for another, broad so as much "reasoning" can be taken away from the LLM as possible. An anti-C. A new take on the goals of Java and Go to be languages that protect the application from the Junior Developers You're Likely To Hire.

      I somewhat think it would also involve application state images ala Smalltalk. LLMs seem okay at generating small deltas. Many deltas sequenced together invites compounding error. LLM generated apps are unlikely to lead to common libraries being compentized and extracted out of the application to share with other applications; it seems like LLM code generation is already a "married to a specific project" act already. So, having a living state image might reveal some benefits by leaning into incrementally developing the application in situ, as a whole.

    • skitsofrandom 19 days ago

      I would guess a good way to implement a language meant for LLMs would be to strip out as many features as possible, so that all programs needed to be composed of just a handful of common structures written in shorthand. As much compiletime enforcement as possible. Maybe human-crafted abstractions for more error-prone concepts like multithreading that limit how they can be used in the language but provide ample, testable bumpers.

      It would be interesting to design some mechanism where an external actor could program extensions into the language easily, which then would become a new black-box tool that an LLM could program with. Ideally though, I think you want to remove as much agency in reimplementation and re-abstraction as possible from the LLM. This is really just some tier above current high level languages, with as much dumbing down as possible.

      I'm not sure this is really necessary or would even be effective because there wouldn't be a million examples for the training data of an LLM. But I imagine something along these lines could make an LLM more productive and token efficient.

    • datakan 19 days ago

      I don't know but I would imagine there are a lot of inefficiencies in modern languages from an LLM perspective that it could strip out, reduce token costs, improve speed etc.

      • SoftTalker 19 days ago

        So, assembly?

        • goosejuice 19 days ago

          That would be less efficient

          • pjmlp 18 days ago

            There are already plenty of PLDI and SIGPLAN talks on LLM => Assembly, with some guardrails for determinism, instead of having a "classical" language as translation layer.

            • goosejuice 17 days ago

              Sorry are we referring to the efficiency of generating programs (i.e. optimizing LLM software development) or the efficiency of the output (i.e. optimizing software through the generation of assembly)?

              • pjmlp 17 days ago

                We are referring to not having to use 3GL languages as intermediate step for LLMs to generate native code.

                "Programming Language Design and Implementation in the Era of Machine Learning"

                https://www.youtube.com/watch?v=Fc3cW0nqAQ0

                • goosejuice 17 days ago

                  I'm not seeing strong claims here on improved token efficiency for general use cases, but it's absolutely not my area of expertise.

                  Completely understandable why this would be valuable research though. Will be interesting to see how it evolves.

phplovesong 18 days ago

Promoting here on HN is not usually allowed. This is a paid tutorial for some obscure programming language.

  • AlexeyBrinOP 18 days ago

    I have no connection with the book author. Also, people post all the time links to paid sources on HN (like books, software or pay for services).

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection