[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)