5 ms·
Little aside, but I feel a lot of the drama surrounding exception could have been solved with a little syntactic sugar making their handling easier. Something a
by grumbel 3y ago
Little aside, but I feel a lot of the drama surrounding exception could have been solved with a little syntactic sugar making their handling easier. Something along the lines of Perl's "|| die("...")" pattern would be a start (i.e. add some context and rethrow).
In C++ I find it quite infuriating that try{} opens up a new lexical scope, which means you can't construct something, check for errors and move on, since the act of adding a try{} means you'd call the destructor of the thing you just constructed. Meanwhile surrounding a whole block of code with a try{} means you no longer can tell where the exception came from.
- mostlylurks 3y ago> In C++ I find it quite infuriating that try{} opens up a new lexical scope, which means you can't construct something, check for errors and move on You technically can with a small workaround (demonstrated below), though I personally wouldn't use this approach. void foo() { auto value = [] { try { return Foo(); } catch (...) { // Something here } }(); value.do_something(); }
- grumbel 3y agoYep, I had to resort to that a few times. With a bit of syntactic sugar that could be turned into something like: auto value = try Foo("will fail") catch(...) { return Foo("will work"); // or throw something else };
- senkora 3y ago> In C++ I find it quite infuriating that try{} opens up a new lexical scope That’s an interesting point. I’ve never considered that because I haven’t worked with classes that regularly throw in their constructors. What situation do you have where 1) you are constructing classes that regularly throw in their constructors and 2) this is a recoverable error that 3) should be handled at the point where the class is constructed instead of some outer point?
- grumbel 3y agoCode like: QImage image("filename.png"); is pretty common. Qt solves this by not throwing an exception and using a Null image check: bool QImage::isNull() const but that throws all the extra information that an Exception could provide away.
- specialist 3y ago> infuriating that try{} opens up a new lexical scope This slays me. The try, catch, and finally blocks should be just one lexical scope.
- xen0 3y agoI don't think that helps? If, as is kind of the point of RAII, your constructors do some initialization and that initialization may fail, then: If you have a single object that may fail to construct then maintaining it in scope for the catch block doesn't make sense; it's not initialized. If you have several, then you still can't maintain them in scope, because you don't know which ones are actually valid. Yes there are other patterns that wouldn't have this issue (acquiring resources outside of the constructor), but then you can just declare your objects outside of the try-catch block.
- specialist 3y agoI misspoke. Ignoring the syntax for a moment, I want scoping to behave like this pseudo-code. So that the catch and finally blocks are lexically nested within the parent try block. try { OutputStream out = ... ... // Must be at end of try block catch ExceptionA, Exception B { ... } catch Exception C { ... } finally { ... } } // end of try Maybe even allow catch and finally to allow single expression in addition to blocks. Just like with if/then/else.
- nemetroid 3y agoIf constructing "out" fails but one of the catch-blocks tries to use "out", what should happen?
- grumbel 3y agoPython is an example of a language that works like this. When the constructor throws, 'out' remains not defined, but you can just do 'out = ...' in the catch block and define one with a fallback value. So all the code after the error handing would just see a working 'out' variable. This works due to all variables being bound to the function scope, not to the code block, in Python.