Remix.run Logo
kaashif 2 days ago

If the idea of computers is that they remember stuff for you and do stuff for you, then both try/finally and defer seem like hacks to work around not having RAII like e.g. Rust or C++ where resources are closed/disposed of/deallocated automatically.

Try X finally dispose of all resources. X, defer clean up X. Or how about just X and cleanup is done automatically, with the author of the resources deciding what is needed to clean X up.

mcintyre1994 2 days ago | parent | next [-]

JS has the using keyword for this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

kaashif 2 days ago | parent [-]

What if you forget to use that and just use let or const? It is better than plain try-finally or defer because you don't have to remember how to dispose of the resources but in terms of remember to dispose of the resource at all, I don't think that is all that different from Python's with or Java's try-with-resources. You can just forget to use using, with, try-with-resources.

There isn't any way to forget to drop a resource if you have RAII.

throw-the-towel 2 days ago | parent [-]

Yes, but you also have this problem with `defer`.

masklinn 2 days ago | parent [-]

And try/finally.

pjmlp 2 days ago | parent | prev | next [-]

Only when doing stack allocations or reference counting, any other heap management strategy and RAII can't help as well.

For example, combining RAII with lock free data structures, which usually ends up in techniques like hazardous pointers instead.

okigan 2 days ago | parent | prev | next [-]

it's mesmerizing that the fantastic ergonomics of RAII have not propagated to other languages.

It's way easier to use, much clear, less typing, more predictable runtime behavior.

RAII... terrible name, great concept!

masklinn 2 days ago | parent | next [-]

RAII has complications in GC’d, fuzzy ownership langages, it becomes much less ergonomic there because now passing an RAII object as parameter to a function causes that function to clean it up, so you need additional mechanisms to bypass this. Same if you just poke an RAII object inside a collection.

Traditionally langages with simpler runtimes simply used destructors for this, refcounting made it deterministic (modulo the old reference leak), but more advanced garbage collection schemes made that stop working.

pjmlp 2 days ago | parent | prev [-]

It only works for stack allocations or when using reference counting, which isn't the ultimate performance of GC algorithms.

Rohansi 2 days ago | parent | prev [-]

I mean, sure, but RAII (in C++, at least) is implemented the same way as this article: with a try...finally block!

RAII doesn't really fit into every language because they don't all have deterministic destructors/finalizers and objects with scoped lifetimes. Sometimes you only have one but not the other and you definitely need both.

okigan a day ago | parent [-]

that's a very broken metaphor - it might be "similar" to try-finally block if you only have one variable/object following RAII. But try-finally block(s) become complete mess when multiple variables are involved, and again requires way more typing/duplication than RIAA. And "similar" in terms of results, NOT similar in terms of performance as try {} block requires additional instructions to set it up, whereas RIAA is runtime free.

And regarding sibling post about finalizers -- another broken concept as you cant use finalizers with limited resources (ex. graphic contexts, db connections, handles, locks, etc) and then these languages that use finalizers become complete mess if you need to manage such resources.

Rohansi a day ago | parent [-]

> And "similar" in terms of results, NOT similar in terms of performance as try {} block requires additional instructions to set it up, whereas RIAA is runtime free.

By similar I meant from the compiler's point of view. `try...finally` is the low level primitive to ensure some code runs at exit. If something throws an exception then destructors must run when unwinding the stack, which is what `finally` is for! But if you disable exceptions then `try` blocks are probably all basically no-ops.