This is another reply to
this thread for it to be clean of unrelated stuff.
Rusky wrote:embroy2 wrote:Object wide scope is not enough for many possible complex states.
False. Object scope is, in fact, whatever you put in an object. Representing an operation's state in a separate struct rather than scattered across the stack is useful for other reasons as well- Iterators are a prime example of this.
I see no arguments here, only some empty statements about your position. Can you elaborate why object scope is better than the exact code where the problem can emerge?
Rusky wrote:embroy2 wrote:The Rust doesn't prevent a developer from writing empty destructor.
It doesn't need to, because library types like locks, vectors, files, etc. already have destructors which will be called regardless of whether their containing object has a destructor, or whether their containing stack frame has a finally block. The only time you need to write your own destructor is if you are wrapping manual resource management, which is rare and already requires you to know what you're doing.
So, you suggest to rely on the default destructors and think no more (because everything else is "rare")?
Rusky wrote:This is objectively better-structured because it gets rid of the out-of-band side channel which is exceptions.
Well, the word
objectively is very impressive, but the arguments are missing again. Why we need some in/out channels when recovering after a problem? I prefer just to see the code, where the problem is going from, and concentrate on the exact situation the code produces. But you, it seems, prefer to concentrate on writing a very general destructors that match every possible problem in every possible situation. I just don't know how it is possible to write such very general destructors.
Rusky wrote:Exceptions, no matter what nonsense you make up about them, still have these bad properties:
- The decision of how to handle them can be ignored, and has a bad default
- When they are ignored, they allow resources and partially-modified state to leak when it should be encapsulated
- When you do handle them, it's verbose and repetitive, which discourages people from handling them correctly
The only problem with exceptions is that they can be hidden by some poorly designed methods. But nobody can ignore the handling decision - everybody always decides to handle a problem or not to handle. Next, any complex state requires some serious thinking about it's recovery in case of a problem and ignoring such situation is really bad practice mostly employed by the very beginners. And finally, nothing prevents you (except some laziness) from extracting a function in case you see some repetitive code.
Rusky wrote:On the other hand, in-band error handling with "Result" still solves these exact problems:
- The only way to get the result you want is by checking for and handling the error
- Checking for and then explicitly ignoring an error does not leak anything out of the function, you must explicitly return an error.
- Because they are in-band, error handling strategies can be factored out into functions and macros
- In-band error handling is less verbose when handling errors, and more verbose when ignoring them, so it encourages people to do things correctly
I can't oppose all those statements because I have no experience of working with Rust, but my general statement is the same - it's always up to the developer and his experience if the error handling is implemented correctly or not. The minor help from the language can improve a bit development speed, but generally is far from enough for not to expect some incorrect problem handling.
Rusky wrote:In the end, the better solution is the one that defaults to making the right choice, or if there is no good default, forces the developer to make the choice. It makes common right choices short and easy to express, and uncommon/usually-bad choices harder. Exceptions do the opposite.
Checked exceptions always enforce the choice between handling them or passing them up along the calling stack, there's just no default, bad or good. And what is the "common choice" depends on the developer. If the language always enforces just one choice, then it is too inflexible and should be used with caution.