5 ms·
> There is nothing about exceptions that's inappropriate for system programming. There's lots about exceptions which is inappropriate for system programming, s
by masklinn 4y ago
> There is nothing about exceptions that's inappropriate for system programming.
There's lots about exceptions which is inappropriate for system programming, starting from FFI unsafety and the lack of signaling to callers (which makes resilient use more difficult).
> If anything it enables the enforcement of strong invariants
It doesn't do that.
> and leads to better and safer code.
It only does that in comparison to truly deficient (e.g. c-style) error reporting, and that's being generous.
- mgaunard 4y agoWell it seems you don't understand exceptions. They eliminate erroneous states entirely, since the objects just don't get created if an error occurs. The alternative that the parent said was making all of your state be a union with some kind of error, and making sure all accesses handle the fact the variable might be in a erroneous state. That is a huge explosion of possible states in your program, and essentially making every invariant weak everywhere. Then FFI, I suppose you mean interfacing with C. Problems that arise when interfacing with other programming languages are orthogonal to a language's ability to be used for system programming. Obviously you wouldn't let an exception propagate through some C code, that's forbidden.
- zozbot234 4y agoYou don't need exceptions for constructors. You can just use static factory functions with an error return as Rust does, and dispense with constructors altogether.
- mgaunard 4y agoEnjoy your combinatorial explosion of states. It's not equivalent at all.
- Yoric 4y agoCould you elaborate? Rust manages pretty well without constructors and I'm nearly certain that it doesn't have any kind of combinatorial explosion of states. Same for ML-family languages.
- jcelerier 4y agoCan you enforce at compile-time that only such a static factory can ever be used for creating the object in Rust? This is the whole point of constructors, they cannot not be used. Otherwise you're just one commit away of creating an object that will not respect the invariants - will you even remember to call this specific factory function in 6 months?
- jstimpfle 4y agoTo me, constructors are mostly a convenience thing for the simple cases where I declare a quick container on the stack or similar, and don't want to waste keypresses to have it constructed. And to me it's a question of, what does the language want to be -- maybe this kind of code is better served by languages like C#. There are various practices that handle the problem of having to call a specific function to get an object in a specific state, without requiring language support. You can make the function that should be used stand out in an obvious way. You can hide the definition of a structure, which very If it is the whole point of constructors to guarantee that the object is in the right state, it could be the best argument why Rust does not have constructors. Programming is chock-full of "this must be called only by that or in this or that context..." and practically speaking, only a part of them can be handled by language objects and construct/deconstruct semantics. Plus, C++ gives enough escape hatches to get not-constructed objects or to un-construct objects without them going out of scope. These guarantees that C++ provides (but not really), they require a ton of baggage like ridiculous initializer lists or 17 different kinds of constructors (to the point where it's sometimes almost impossible to tell which will be called), or requiring an out-of-band mechanism (exceptions) to signal construction failure.... that's not worth it in my book.
- zozbot234 4y agoYou get this by default for any object with non-public fields.
- ginsider_oaks 4y agoSure, just make the fields of the struct private and you can make a public constructor: https://doc.rust-lang.org/rust-by-example/mod/struct_visibility.html https://doc.rust-lang.org/rust-by-example/mod/struct_visibil...
- masklinn 4y ago> Well it seems you don't understand exceptions. They eliminate erroneous states entirely, since the objects just don't get created if an error occurs. Error sum types do the exact same thing. > The alternative that the parent said was making all of your state be a union with some kind of error, and making sure all accesses handle the fact the variable might be in a erroneous state. Which is a non-issue as it is lifted to the type system. The type system will not let you forget about that. > That is a huge explosion of possible states in your program, and essentially making every invariant weak everywhere. You get an error state added to a given value, which you also get via exceptions, except implicitly and without notification of the additional state. Type-safe error values also provide simpler error handling and recovery in many case, because they don't require split-path handling. > Then FFI, I suppose you mean interfacing with C. Problems that arise when interfacing with other programming languages are orthogonal to a language's ability to be used for system programming. It very much isn't, part of the system programming workload is to provide reusable components. > Obviously you wouldn't let an exception propagate through some C code, that's forbidden. And rarely if every checkable statically, hence unsafe.
- mgaunard 4y agoThe problem is not "forgetting about it", it's that it increases the possible values of your working set. If you have 3 variables, each of which can be in 10 states, that's 10^3 states your program can be in. If instead you have 11 states because all your variables are actually unions with an error, that's 11^3 states (assuming all error states are equivalent to a single state). Now in practice it's even worse since what you care about isn't the possible states of your values, but rather how many different paths you have in your control flow to handle them. Then you're comparing 1 (none of my values are in an erroneous state) with 2^3=8 (any of my values can be in an erroneous state or not). What exceptions do is enforcing that your working set does not have to encode any erroneous states, preventing the combinatorial explosion of states, which of course is a net win, there isn't really any valid argument that can be made against it. Where people are debating is that sometimes you do want errors to be part of your working set, in which case you shouldn't use exceptions. But choice is difficult for some, especially those seeking absolute doctrines. > It very much isn't, part of the system programming workload is to provide reusable components. That's already somewhat dubious, since a lot of system programming tasks are really purpose-built for a usecase or for specific hardware, and regardless, there is nothing about that which has anything to do with interfacing with C. I do a lot of system programming and I write it all in C++, which has a lot of advantages over C beyond exceptions.
- mike_hock 4y ago> They eliminate erroneous states entirely, since the objects just don't get created if an error occurs. EPIPE Erroneous states can arise outside of your control at any time.
- jcelerier 4y agoSignaling to caller has already been shown to be a complete mistake with java checked exceptions, I don't understand why people persist with this. It makes for ridiculous code.
- jstimpfle 4y agoAre you saying that "not signaling" has not been shown to be a total maintenance nightmare as well? Because the only way it is not ever a maintenance nightmare is when you really don't care that function execution could be aborted at any point without any visual clue. And the only way I can see you wouldn't care is when you go 100% in to everything-context managed / RAII or similar. And that again, sorry but I can't be arsed to prematurely rip everything into little pieces like that. It makes for terrible code IMO.
- mike_hock 4y agoBut you can be "arsed" to write an error handler after almost every single function call?
- jstimpfle 4y agoI explained here that I consider having to check many return values to be a smell: https://news.ycombinator.com/item?id=34217251 https://news.ycombinator.com/item?id=34217251 And from my own experience, no I don't have to check a lot of return values.
- masklinn 4y ago> Signaling to caller has already been shown to be a complete mistake with java checked exceptions It's not signalling which has been shown to be a complete mistake, but checked exceptions, more specifically as implemented by Java. Signalling works just fine and is actually rather enjoyable when done well.
- kllrnohj 4y agoCan you point to an example? What has "signaled exceptions"?
- blub 4y agoExceptions have their uses, including in system programming. There’s in fact nothing about system programming which makes a particular error handling method better or worse. These are the kind of minor points some programmers like to fixate on and then sell as the one true way of doing X, while providing no proof and asking everyone to trust them, because it worked great in a project once for the comment author. Not letting exceptions escape at API boundaries has been a technique for a few decades. It’s not rocket science. Writing exception-safe code is likewise an ancient technique by now. Meyers’ books which explained such things were published in the 90s…