Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't think Java finalizers should be considered in the same bucket as C++-style destructors. They are very explicitly not about RAII.

If explicit destruction is desirable, IMO the C#-style `using` pattern (try-with-resource in Java, `with` in Python etc) makes more sense than `defer` since it still forces the use of the correct cleanup code for a given type while retaining the explicitness and allowing linters to detect missing calls (because destructability is baked into the type). `defer` is unnecessarily generic here IMO.

In JS, you still end up having to write try/finally for anything that needs explicit resource management, so I don't think it's a good example. They are adding `using`, though, and TS already provides it.



That's fair, my phrasing was less than precise. More accurately:

I think that automatic and outside-of-written-code destruction is generally a risky/bad idea for nontrivial (in-user-memory only) objects. Both GC-ful languages' finalization systems and the automatic-destruction side of RAII are problematic.

I agree that moving more logic into explicit acquire/perform/destroy blocks like TWR and 'with' is good. I wish we had a language (rather than, say, just specific libraries) that could require such handling for certain datatypes.


Requiring it for certain datatypes would be tricky given that the pattern doesn't scale once you start composing data - if I have class AB that owns an A and a B, in a world with explicit cleanup, I can't express that with a with-block - I have to write AB.close() that does A.close() and B.close().

Now, if you track ownership, you could enforce this. But it seems like at this point you might as well just have proper destructors, since ownership is explicit in the declared type of the variable, and thus having an additional keyword like "defer" is redundant wrt making that destructor call explicit. You just need to make sure that syntax for variable declarations makes ownership or lack thereof very clear.

Separately from that, explicit destruction doesn't resolve many of the issues that you have mentioned with C++ specifically, such as exception safety. Again, in the example above, what should happen if A.close and B.close both throw? A naive implementation would propagate the exception from A and leak B. A fancy one will throw something like Java's SuppressedError, but that's still far from ideal. Similarly, with object state during incomplete initialization, the explicit destructors still have to handle all that somehow.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: