4 ms·
Or Google dialect. Rust, anyway, captures this foolishness in a macro, which saves lines of source code, but still costs cache footprint, branch predictor slot
by moloch-hai 4y ago
Or Google dialect.
Rust, anyway, captures this foolishness in a macro, which saves lines of source code, but still costs cache footprint, branch predictor slots, and runtime.
- tialaramex 4y agoThe Rust try! macro, which I assume is what you're thinking of, has been obsolete for many years - you can still refer to it because the Rust compatibility promise is taken more seriously than in C++ but you will need to use rather awkward syntax to get at it in modern Rust editions since the keyword "try" is reserved since 2018 edition. These days you'd use the Try operator ? which is not a macro, it's an operator. Try is really interesting, it's a unary operator so it takes a single parameter and it maps that parameter into a control flow decision. For Result the effect is similar to what you got out of the try! macro, but of course this operator can be implemented on any type. The standard library provides six implementations, including famously on Option, but also on ControlFlow itself, which is pretty nice. This means across a complex system you can choose to collect Results, and decide what to do about the Results later, (perhaps after you have all of them, or after you've a certain amount) or you can choose the same for the ControlFlow decisions resulting from those Results. You can also turn things on their heads, and decide that what you want to do is return early on success, but continue processing for errors -- which is something that's just unthinkable in an exception world where control flow and success are somehow the same thing. Rust took some years to figure out that's just not true which would be embarrassing if the assumption that it's true wasn't baked into the entire C++ language.
- moloch-hai 4y agoYou still wouldn't want to throw for the success case, so the point is meaningless. And of course you can return early on success in C++, and continue to process details further otherwise, with zero difficulty, so there is no cause for embarrassment. Rust people should be embarrassed if they carved out something special for this niche case.
- tialaramex 4y ago> And of course you can return early on success in C++, and continue to process details further otherwise, with zero difficulty Alas, C++ exceptions don't permit this, on failure the exception will get thrown and control flow switches away without any opportunity to intervene. That is in fact its whole purpose. That's the design mistake, it's not something you can fix, it's a choice which seemed clever last century, and it's last century's design.
- moloch-hai 4y agoIt is in fact absolutely trivial to do, if you care to. But of course it is vanishingly rare to want it, so you don't see it much. If you cannot figure it out, find someone to explain it to you, instead doubling down when your falsehood is pointed out.
- tialaramex 4y agoI'm guessing you're thinking of capturing and hauling around exception_ptrs ? But that's far from "trivial" - it involves needing to understand how the temporary objects which were constructed in some "unspecified storage" work and then wrangle this custom smart pointer. In contrast Rust's Result and ControlFlow are just ordinary sum types, no magic involved.
- moloch-hai 4y agostd::optional<T> f() { try { return it(); } catch(...) { clean_up(); return {}; } } Trivial. If you don't want to throw away the exception: T f() { try { return it(); } catch(...) { clean_up(); throw; } } But of course cleanup code belongs in a destructor, so nobody does that. In C++, we say T f() { return it(); } and the responsible destructor does its job, either way.
- tialaramex 4y agoThis seems like you didn't even grasp what the problem was, let alone try to solve it.