4 ms·
You appear to be using "generic" to mean "C-ish". That is not what the word means, in context, and there is no reason to do any of it anyway. "Proofing the code
by moloch-hai 4y ago
You appear to be using "generic" to mean "C-ish". That is not what the word means, in context, and there is no reason to do any of it anyway. "Proofing the code"? Does that mean anything at all?
For RAII on heap objects, you have std::unique_ptr, and no boilerplate. Anyone failing to lean into RAII to manage resources is just choosing to write unreliable code. Or C, but I repeat myself.
- mgaunard 4y agoDue to language limitations, a lot of C programmers make all their variables shared pointers, which means they don't have to figure out how to do value semantics, moving and copying objects, especially in multithreaded environments. Interestingly, it seems Rust programmers do the same too, because otherwise programming in Rust is too hard.
- jstimpfle 4y ago> Due to language limitations, a lot of C programmers make all their variables shared pointers, which means they don't have to figure out how to do value semantics, I wouldn't approve. Make shared (i.e. ref-counted) pointers when actually needed. Writing C is best when not mimicking bigger languages (i.e. with GC), but when figuring out how a system can work optimally.
- mgaunard 4y agoYou might not approve, but the reality is that most C code is built like that.
- secondcoming 4y agoI assume you mean C++ here? In any case, in my experience this bad practice comes from Java devs who’ve moved to C++.
- moloch-hai 4y agoJava Disease is its own topic. But most shared pointer ownership in C is wholly ad hoc, without even reference counting.
- mgaunard 4y agoNo, I mean C. People don't do that in C++, since C++ provides ways to define value semantics (copy, move, assignment).
- tialaramex 4y agoYour theory is that Rust programmers "make all their variables shared pointers" ? Even if I generously assume you're thinking of C++ "shared pointers", and so you've concluded that Rust's Rc<T> (a reference counted T) is basically the same thing, I don't see where you'd come to the conclusion that Rust programmers do this for "all their variables" as this seems wildly unlikely.
- mgaunard 4y agoJust look at the code in cargo. (A)rc is all over the place. It's essentially a cop out to not have to think about ownership and lifetime, and not have to worry about the borrow checker. The fact that this is so pervasive throughout Rust code is for me a sign that Rust failed to deliver on its initial promise. The borrow checker was meant to be its main value added. But heh, people still find value added to Rust otherwise.
- tialaramex 4y agoHmm. So the code I happened to have open was Aria's "Cargo mommy" which has neither Arc nor Rc anywhere, but is only a toy. So I did go look at Cargo itself, but unlike you although I do see some use of Rc and fewer of Arc it was scarcely "all over the place" when I looked and in the cases I spent any time actually thinking about it's a shared value, so, yeah, that makes sense. I randomly looked at cargo/core/profiles.rs and cargo/core/registry.rs and cargo/core/compiler/compilation.rs without finding either Rc or Arc used in those files at all. Searching across the whole repository I found some places which do use Rc, and fewer using Arc (implying this data is shared between threads) -- but this doesn't really support your original claim does it?
- mgaunard 4y agoI never meant cargo itself.
- zozbot234 4y ago> It's essentially a cop out to not have to think about ownership and lifetime Not a cop out. Something very much like Rc<> is needed whenever an object's lifecycle might be independently extended by multiple referencing "owners", none of which is subsumed by the others. That's a matter of broad high-level design that can't generally be avoided, least of all in a multi-threaded context (as shown by the use of Arc<>).
- jstimpfle 4y ago> "Proofing the code"? Does that mean anything at all? Since you're already schooling me on the meaning of terms, you probably have enough experience to have realized that the typical code begins life in a stubbed out form that is barely functional enough to deliver first results. It is then iteratively enhanced and made more widely applicable, more robust, more refined, better specified, more performant, and so on. In the process, the code is undergoing many revisions, and moving data structures from automatic storage (stack) to the heap is very typical. Another word I'm thinking of for this process is "consolidation", which I have also used. My apologies if I don't speak in your terms / in the most precise terms.
- moloch-hai 4y agoI don't have experience of this "moving from ... stack to the heap", in C++. Correct code is the same wherever the objects live, whether stack, member, or heap. Changing it costs time and adds faults. This proofing process is another example of what makes coding C more costly and buggy than coding C++. I did it for years, and miss it not at all.
- jstimpfle 4y agoIf writing systems-level code solving for non-trivial requirements, the majority of the state has a lifetime that outlives any particular function call. That's when you need to move that state to the heap. There's no clear scope anymore, ownership has to be moved from function scopes to RAII managed container structures. Things are quickly getting more complicated and expensive (software complexity/bloat, compile times, binary size...) when you have to nest your structures in templated containers that don't know what you're nesting in them... This is where all the complexity with 17 constructor types and 99 move semantics with const, non-const, r-valued references and abstract virtual base classes came from, and there might be less than a dozen persons left on the planet who really understand it all...
- moloch-hai 4y agoWith RAII, it is trivial to move things from stack to heap, or to a member of something that might be on the stack or heap or in a container, without changing any of the code that implements the object. Most usually you don't need to declare or define any constructors, assignment operators, or a destructor; the compiler provides them, and guarantees they are correct. (Sometimes you provide one constructor as a convenience for users.) It has been many years since I found a use for an abstract virtual base class. Literally millions of people understand it all, and use it every day with no difficulty. You don't need to invent difficulties, or waste days "proofing" code that may be written exactly once and never touched again.