5 ms·
wish defer made it, so I can kind of do RAII. even better, adding constructor and destructor for RAII in c, main() has it via attributes __constructor__ __dest
by synergy20 4y ago
wish defer made it, so I can kind of do RAII.
even better, adding constructor and destructor for RAII in c, main() has it via attributes __constructor__ __destructor__, gcc has __cleanup__ for non-main() functions too, let's add it to C directly?
- KingLancelot 4y ago
- masklinn 4y ago> even better, adding constructor and destructor for RAII Constructors are a nuisance, and destructors while great require significant additional semantics to avoid double destruction. C++ uses unconditional destructor thanks to ubiquitous copying and non-destructive moves, but that requires all objects to always be in a destructible state. Rust instead relies on lexical drop flags inserted by the compiler if objects are conditionally moved. They’re more convenient and composable than defer/cleanup/scope, but they also have more langage impact. Obviously the trade off is defer pushes that issue onto the developer.
- mjburgess 4y agoI suspect `defer` is the mainstream right tradeoff between the implicit nightmarish semantics of C++ and the formalism of rust. I think the Rust view of C++ will turn out to be an over-reaction. The issue wasn't a failure to make the implicit explicitly provable, it was simply to make it explicit at all.
- masklinn 4y ago> I suspect `defer` is the mainstream right tradeoff It’s not. It’s a conveniently simple language addition which foists all the issues and edge cases onto the language user. Defer is a limited subset which is more verbose and more error-prone. However like “context managers” (e.g. try blocks, using, with, unwind-protect, bracket) it also works acceptably in languages where ownership concepts are non-existent or non-encoded, whereas destructors / drops require strict object lifetimes. > The issue wasn't a failure to make the implicit explicitly provable, it was simply to make it explicit at all. What, pray tell, would be the use of making borrows “explicit” then ignoring them entirely? Useless busy work?
- mjburgess 4y agoWell i didn't mean only defer, context managers also count as a 'making explicit'. My point is that requiring compile time proofs is likely too far to reach the practical goal. Indeed, it seems most Rust code today agrees: widely turning off the borrow checking with copies and the like.
- jamincan 4y ago> Indeed, it seems most Rust code today agrees: widely turning off the borrow checking with copies and the like. I here this and that `unsafe` is widely used in Rust code bases repeated a lot, but is there any actual data backing this?
- mjburgess 4y agoThere are three "dialects" of rust: borrow-checked, unsafe, and copy-everything. The existence of these three "dialects" goes to my point that the borrow checker isnt The Ideal solution to the problem of high-perf. safe static computing.
- anonymoushn 4y agoSome of this data may be difficult to collect, because some project leads evaluate Rust, discover that the entire ecosystem is built on top of libraries that endlessly thrash a global allocator with synchronization primitives in it, and move on.
- Fredej 4y agoOh man, no defer? Bummer. I'm switching from C++ to C recently and there sure are a bunch of things I'm missing!
- AlbertoGP 4y agoI made a small pre-processor that implements block-scoped defer in C, by transforming the source to add the deferred code at each exit point in a function. It is called Cedro: https://sentido-labs.com/en/library/cedro/202106171400/#deferred-resource-release https://sentido-labs.com/en/library/cedro/202106171400/#defe... That link goes directly to the relevant section in the manual. It includes a cc wrapper called `cedrocc` so you don’t need intermediate files, and it works hard to produce clean code for the generated parts. The rest is not modified at all. The goal is to be useful even if you only use it once to generate that repetitive code. The pre-processor `cedro` depends only on the C standard library, and `cedrocc` depends on POSIX.
- unwind 4y agoUh, not to be That Guy, but what did you expect? Just compare K&R [1] and Stroustrup (any edition) [2] next to each other, and you will get a pretty strong hint of C being a smaller language. That's kind of the point, or it used to feel like it was anyhow. [1]: https://en.wikipedia.org/wiki/The_C_Programming_Language https://en.wikipedia.org/wiki/The_C_Programming_Language [2]: https://www.stroustrup.com/4th.html https://www.stroustrup.com/4th.html
- pjmlp 4y agoFirst of all, if you are comparing K&R against Stroustrup, then you should use C++ARM, not later editions. Secondly, Bjarne's books include the overview of the standard library, which neither K&R nor its ANSI C revision do. Third, since everyone keeps using compiler extensions in C, moreso than in C++, those should be included as well.
- unwind 4y agoAt least in my ancient copy (second edition, from 1988 I think) K&R most definitely has an overview of the standard library, in Appendix B.
- quelsolaar 4y agoI'm in the wg14, and I made a passionate argument against defer. C is all about simplicity and clarity, over conviniance. Defer, is an invisible jump, its much better using a goto, that clearly denotes a change in flow. In C everything should be as clear and as explicit as possible. Nothing should happen without the user explicitly saying so. This means more typing, and thats fine, there are plenty of languages that offer loads of syntax sugar if thats what users want, but only C offers clarity.
- klodolph 4y agoI think this is the right approach. You can make C better without trying to compete with newer languages.
- pjmlp 4y agoYeah, why bother competing with newer languages on safety, that was never something that mattered on C's design.
- enriquto 4y agoThank you so much for your work! Your comment made me happy and warm inside, as if there's still some order in this crazy world. As if there's still a few sane and robust things that we can attach ourselves to, knowing that they will not break. How can we support/encourage you? (in case you need it)
- quelsolaar 4y agoSpeaking up is a good start! The support is much apprechiated!
- secondcoming 4y agoIf C is simple and clear why is it fraught with pitfalls? While C code can be nice and clear to read that doesn’t mean there less mental burden on the developer to keep track of everything going on.
- flohofwoe 4y agoA sane defer-like mechanism would be fine with me, but please no destructors (or worse) constructors, they are much too inflexible because they bind 'behaviour' to types. Data should be 'stupid' and not come with its own hardwired behaviour, otherwise this becomes a design-rabbit-hole that eventually ends up in C++.
- masklinn 4y agoWhile I agree that destructors are unsuitable for C, that’s because for them to be useful you’d have to throw out and redo the entire standard library, so they can’t be usefully retrofit in the language, however > they are much too inflexible because they bind 'behaviour' to types 1. that is the baseline you want, data is not an amorphous and meaningless blob, the default for a file or connection is that you close it, the default for allocated memory is to release it, etc… 2. that also allows much more easily composing such types and semantics, without having to do so by hand 3. and is much more resilient to future evolution, if an item goes from not having a destructor to having one… you probably don’t care, but if it goes from not having a cleanup function (or having a no-op one which you could get away with forgetting to call) to having a non-trivial cleanup function you now have a bug lurking 4. destructors also make conditional cleanups… just work, the repetitive and fiddly mess is handled by the computer, which is kind of the point of computers, rather than having to remember every time that you need to clean the resource on the error path but not on the non-error path, defers easily trigger double-free situations; this also, again, make code more resilient to future evolutions (and associated mistakes) 5. furthermore destructors trivially allow emulating defers, just create a type which does nothing and calls a hook on drop > Data should be 'stupid' and not come with its own hardwired behaviour That’s certainly a great take if you want the job security of having to fix security issues forever.
- flohofwoe 4y ago> ...the default for a file or connection is that you close it... Something like a file or connection is already not just 'plain old data' though. In my mind, 'data' are the pixels in a texture (while the texture itself is an 'object'), or the vertices and indices in a 3D mesh (while the 'mesh' is an object), or the data that's read from or written to files (but not the 'file object' itself). C is all about data manipulation (the 'pixels', 'vertices' and 'indices'), less about managing 'objects'. For objects, constructors and destructors may be useful, but there are plenty cases in C++ where they are not (textures and meshes in a 3D API are actually a good example for where destructors are quite useless, because when the 'owner' of the CPU side texture object is done with the object doesn't mean that the GPU is done with the data that's 'owned' by the CPU side object - traditional destructors can be used of course by delaying the destruction on the CPU side texture object until the GPU is done with the data, but why keep the texture object around when only the pixel data is needed by the GPU, not the actual texture object? A 'defer mechanism' is just the right sweet spot for a C like language IMHO.
- rwmj 4y agoDefer was a truly terrible suggestion (as presented). However the C committee should have standardized the widely used __attribute__((cleanup)).