4 ms·
You 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 proces
by moloch-hai 4y ago
You 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.
- moloch-hai 4y agoI solved the right problem, instead. Your "sum type" is a workaround for lack of a fundamental language feature. We don't need that workaround.
- tialaramex 4y agoThere are two sum types here, and the fact they're different is the insight. The try! macro didn't have that insight, and the first attempt to make a Try operator didn't either, but the current one does. This sort of experimentation is not available in practice to C++ but that would only slow it down a little, what prevents forward motion far more is that WG21 doesn't want to learn from other people's experiments. C++ 23 gets std::expected which is, modulo IFNDR nonsense, a Result type. But C++ 23 doesn't have, and none of the further papers propose, a type analogous to ControlFlow. I actually wondered how C++ 23 does the equivalent of Iterator::try_fold without ControlFlow, how do they express this idea? Did they use std::expected here as once Rust used Result ? The answer seems to just be "They don't" which I think gets to the heart of it. A resumable, short-circuiting fold would be just as useful in C++ as it is in Rust, but it's easy to express nicely in Rust and doing so in C++ would insight anger from Exceptions purists, so that likely won't happen.