[HN Gopher] Ask HN: What should have been the term for RAII?
___________________________________________________________________
Ask HN: What should have been the term for RAII?
Bjarne Stroustrup himself said he was very busy when he came up
with the name for this concept, that it's not a very good name, and
joked he's not good at "marketing". What would be a better
terminology? As I've been learning modern C++, I admit that I've
struggled to understand why these terms make sense. To me, I think
of it like "Resource Acquisition Promising Release". Does this
betray that I am not truly understanding Strourstrup's principle?
Author : beaukin
Score : 32 points
Date : 2022-06-04 14:55 UTC (8 hours ago)
| helionsantos wrote:
| Managed resource lifetime
| codeflo wrote:
| BTW, a lot of people in this thread compare destructors to Java's
| try-with-resource (similarly, C#'s using), or Go's defer.
|
| Here's one important difference: Destructors work in standard
| data structures. If for whatever reason you want to build a
| map<string, list<fstream>>, and the map goes out of scope, all
| files are correctly closed. (Rust's drop semantics work the same
| way.) That's a lot more work in Java or C#.
| blt wrote:
| I would just call it "destructors". It's a little imprecise
| because some GC languages also have destructors, but arguably
| they shouldn't.
| spyremeown wrote:
| Constructor Acquires, Destructor Releases.
| AlbertoGP wrote:
| I too was going to say this!
|
| The earliest mention of this idea (CADR / CADRe) I've found is
| from 2012: https://groups.google.com/a/isocpp.org/g/std-
| proposals/c/Una...
| klyrs wrote:
| Unfortunate acronym, you're going to get a bunch of lisp
| docs...
| kazinator wrote:
| It's also pretty pointless; it's just repeating the job
| description of the constructors and destructor of any
| object that manages a resource.
|
| Who is that for? Dummies who get it backwards? Oh, look,
| you're releasing in your destructor and acquiring in the
| destructor. Did you forget your CADR?
| AlbertoGP wrote:
| You are right, I do program in LISP and love the C[AD]+R
| idea.
|
| I even had my own proposal 5 years ago for improving
| _that_!
|
| > _That 's right, but I would go one step further and have
| F(irst) and R(est), with obvious composition as follows:
| (using kruhft's examples from another thread)_
| > (ff x) == (caar x) == (car (car x)) > (rrf
| x) == (cddar x) == (cdr (cdr (car x)))
|
| > _I would argue that it 's worth sacrificing the 'f' and
| 'r' symbols for such a common construct._
|
| > ...
|
| > _Yes, I realize I 'm 55 years late to the party._
|
| https://news.ycombinator.com/item?id=13259344
|
| Now we only need to implement _both_ changes at the same
| time! :-P
| kazinator wrote:
| The only problem is that the car and cdr are not the
| first and rest of anything, when they are just used for
| tree structure.
|
| Only when the tree structure conforms to certain
| conventions and intent of representing a list is the car
| "first" and the cdr "rest".
|
| So of course those names are fine for nested lists: (ff
| '((a b c) d)): the "first of the first". But in, say, an
| assoc list ((a . 3)) 3 is not the "rest" of anything;
| it's the value of the key a.
|
| The proposed functions go with the first and rest
| functions, rather than replace the cddr ones.
|
| Now let's talk about something else: the order. In caddr,
| the order is just a condensation of the nested
| application of (car (cdr (cdr ...))), in the same order:
| it's easy to convert between the two, both actually and
| mentally. However, in left to right threading syntax,
| it's backwards: (flow value car car cdr
| (+ 1))
|
| corresponds to (+ 1 (cdr (car (car
| value))))
|
| so it condenses like (flow value cdaar
| (+ 1))
|
| You can see someone wanting a variant which has the
| letters in the opposite order.
|
| With f and r functions, you can do:
| (flow value f f r (+ 1))
|
| which is almost the backwards "ffr" you might want.
| potiuper wrote:
| In C++, if the construction fails (with an exception), no other
| member function - not even the destructor - gets called and the
| resource is not acquired.
| opportune wrote:
| This is one reason many people think exceptions in C++ are
| harmful, they cause unclear implicit behavior. Much better to
| handle a failure explicitly outside the constructor
| benibela wrote:
| This is one reason I use Pascal
|
| If the constructor throws an exception, the destructor is
| called immediately.
| kevinossia wrote:
| I always just referred to it as "deterministic destruction." I
| think that's reasonable, anyway.
| z3rgl1ng wrote:
| klyrs wrote:
| After not much thought on the matter, I'd call it Resourceful
| Instantiation.
| DougBTX wrote:
| cppreference defines it as:
|
| > Resource Acquisition Is Initialization or RAII, is a C++
| programming technique[1][2] which binds the life cycle of a
| resource that must be acquired before use (allocated heap memory,
| thread of execution, open socket, open file, locked mutex, disk
| space, database connection--anything that exists in limited
| supply) to the lifetime of an object.
|
| I'd crib the name from Rust, this is ownership, where the object
| owns the resource.
| andrewflnr wrote:
| I tend to use "deterministic finalizers" for the part that (in my
| understanding) is the most critical
| beaukin wrote:
| Wow, such good ideas here. I guess no one is keen on my "RAPR"
| proposal :) But just to reflect a bit more, I think my
| curiosity/confusion stems from the "is initialization" wording,
| and how the word "initialization" in the context of C++ will
| imply a guaranteed freeing step?
|
| I've tried reconciling how its defined here:
|
| https://en.cppreference.com/w/cpp/language/initialization
|
| However, it seems like wording describing ideas around how a
| resource is created, and not how it's completed.
| Dwedit wrote:
| Autofree
| datalopers wrote:
| Can we use some wilderness phrases like "Pack It In, Pack It Out"
| or "Leave No Trace"?
| qbasic_forever wrote:
| Hah, my vote is for LNT!
| watmough wrote:
| I think _scope_ or similar is good.
|
| Also, see related video here CppCon 2015: Andrei
| Alexandrescu "Declarative Control Flow"
| https://youtu.be/WjTrfoiB0MQ?t=1046
| klabb3 wrote:
| "For dust thou art, and unto dust thou shall return"
| leereeves wrote:
| And for short, perhaps "dusting".
| tester756 wrote:
| it sounds like Disposable
| daenz wrote:
| Something with scopes? "Scoped resources" ?
| hyperman1 wrote:
| The most important part for me is not construction,but the
| guaranteed destruction. So what about:
|
| Resource Is Getting Guaranteed to End up Destructed.
|
| I try to have RIGGED as backronym, but the words are not
| completely right. Even so, the slogan could work like this:
| Prefer using RIGGED resources in C++
| beaukin wrote:
| Nice!!
| potiuper wrote:
| Resource Encapsulation
| jolux wrote:
| I'm a Rust programmer but I would call it scope-based or scope-
| bound resource management, a popular alternative term in the C++
| community.
| jeffbee wrote:
| RAII isn't just about automatic ("scope-based") variables. RAII
| refers to the way the language ties together the construction
| and allocation of the object.
| jolux wrote:
| Are there languages that do SBRM but not RAII?
| codeflo wrote:
| Rust doesn't have initializers in the C++ sense. And I
| mean, even in C++ many classes like shared_ptr or even
| lock_guard have constructors that don't acquire the
| resources yet. When the resource is acquired is an API
| design concern; the important part is where it's released.
| jolux wrote:
| This sounds like an argument that C++ isn't RAII.
| somedudetbh wrote:
| C++ _isn't_ RAII. RAII is a design pattern you can apply,
| leveraging C++ language features, in C++ in certain cases
| to avoid a certain class of bugs.
| jolux wrote:
| Well sure but I would assume the pattern would be
| consistently implied in the standard library, no?
| jeffbee wrote:
| The standard library necessarily has broad coverage of
| many use cases. That's why not every constructor of
| lock_guard acquires the lock. It's a completely
| legitimate use case that your thread happens to have a
| lock and wishes to use the end of lifetime of a
| lock_guard to release it. It's the same reason that you
| can construct a unique_ptr from an object that was
| allocated with new instead of with make_unique. Also,
| it's perfectly analogous to Go's `defer mu.Unlock()`.
| beaukin wrote:
| I'm not an expert, but I would so no, it's not. The point
| of learning to implement with RAII, in the context of
| C++, is so that one will apply it to use C++ in a more
| resource safe way. It will help avoid the bugs that the
| language will inherently allow if the programmer is not
| being otherwise being careful.
| mhh__ wrote:
| D has constructs: scope(exit) foo(); //
| Call foo at the end of the scope scope(success)
| foo(); //Call foo if all goes well scope(failure)
| foo(); //Call foo if the wings fall off the plane.
| light_hue_1 wrote:
| Plenty of languages don't have RAII have SBRM. Scope based
| resource management predates the idea of constructors by
| decades. It's common in Lisp and Scheme. Haskel doesn't
| have RAII, but scope-based resource management is critical.
|
| ``` (call-with-output-file some-file (lambda (out) (write
| 'hello out))) ```
| Matthias247 wrote:
| Yes. Eg if you look at Java try-with-resources there is an
| exact scope during which resources live and can be used. At
| the end of the scope the .close() method will be called.
|
| For C++ and Rust there might not be a well defined scope
| since objects can be ,,moved". Eg a method constructing an
| object can return it to the caller without the destructor
| being called.
| jolux wrote:
| It's well-defined, it's just more flexible than Java. The
| difference is that returning a value moves it, and
| resources are owned by the creating scope by default.
| Java doesn't have the same concept of ownership, or
| rather, you can't move values in Java.
| remram wrote:
| Python's with keyword maybe?
|
| You can do with lock: # lock
| is held # lock released with lock:
| # lock is held again
|
| Also Go's defer keyword, which is bound to the current
| function (defer until function returns).
| jolux wrote:
| Right, but those are opt-in features. In Python you can
| lock something and not release it by mistake. In Rust
| this pattern is enforced, the destructor will always
| release it at the end of the enclosing scope unless there
| is a panic or infinite loop. I think this is a
| substantive difference.
| tazjin wrote:
| It's not enforced in Rust, but it's automatic unless you
| actively prevent it from happening. So you could say it's
| an opt-out feature.
|
| std::mem::forget is considered safe, as explained in its
| docs: https://doc.rust-lang.org/std/mem/fn.forget.html
| jolux wrote:
| Fair enough, yeah.
| [deleted]
| klyrs wrote:
| > I would call it scope-based or scope-bound resource
| management
|
| RAII isn't about scope, it's about lifetimes that can persist
| beyond the instantiating scope. More like object-bound resource
| management.
| jolux wrote:
| Scope is a necessary part of it too though. There's always
| going to be one owning scope for an object in Rust (unless
| you're using Rc) and that scope is responsible for calling
| the destructor. You can change which scope is responsible by
| moving it, but scope is still important. Without scope being
| an implicit part of resource management, you have a feature
| like try/finally or with in Python.
| klyrs wrote:
| You're still trying to make this about rust without
| bothering to learn what the C++ users here are talking
| about. I'm not sure what to tell you.
| xedrac wrote:
| Many RAII objects really are tied to a simple scope - such as
| std::lock_guard. So it's not just about persisting beyond the
| initial scope. I don't recall the word "lifetime" being used
| in the C++ world before Rust came along. The word "scope" was
| often used in the same way we talk about lifetimes now. And
| if you think of the space between an object's constructor and
| its destructor as a scope, then anything that it owns is tied
| to its own scope. In this way, calling it "scope-based" is
| rather intuitive. The only wrinkles would be objects that are
| tied to multiple scopes (reference counted), and objects that
| change scopes (move semantics), but even then it's not hard
| to reason about. Regardless, the term RAII is widely
| understood, so I'm not sure it needs a new name.
| charlieflowers wrote:
| https://stackoverflow.com/questions/712639/understanding-the...
| pavlov wrote:
| DRR, destructor resource release. At least that's the relevant
| part to me...
___________________________________________________________________
(page generated 2022-06-04 23:02 UTC)