the Stu programming language (stu_lang) wrote,
the Stu programming language

RAINA - Resource Acquisition Is Not Allocation

C++ introduced the slogan RAII--Resource Acquisition Is Initialization--a misnomer since the important part of the idiom is _deacquisition_. The C++ idiom's viewpoint is roughly "we have a good model for initializing/deinitializing data as it is allocated/deallocated--constructors and destructors--and applying this to resource acquisition eases the task of deacquisition". So a more accurate slogan might be RAIA: Resource Acquisition Is Allocation. The thing is, the C++ metaphor is nice for lexically scoped resource acquisition, but otherwise it's pretty messy (auto_ptr and all its ilk). In fact, RAIA is important in the face of things like exception handling because C++ doesn't offer any other simple mechanisms for coping with exceptions.

RAIA does not, in fact, play nice with garbage-collected allocation; exposing finalization to users is fraught with peril. Hence Stu's slogan: Resource Acquisition Is Not Allocation. (Stu also strikes this pose because I am against viewing all problems as nails for the OO hammer.) What's needed is a different lexically-scoped resource acquisition scheme, one which deals with exceptions.

Stu introduces two mechanisms. The general flexible mechanism is the => statement delay operator, which causes the statement following it to be executed when the current lexical scope ends (or when an exception is thrown). So if we had a C-like file I/O library, we might write this:

   f := fopen(filename, "r") => fclose(f);
   ... do stuff ...
   if [bad thing happens] then return none; endif;
   return result;

Note that this assumes that if fopen() fails it returns none and fclose() accepts none simply to simplify this sort of code. (The first thing the code will actually do is 'cast away' none, since fread()/fgets() sorts of codes probably won't accept none.)

The second mechanism I want to design is to make the above more automatic. We write a single wrapper function around fopen and fclose which returns a tuple containing the filehandle and a void(void) closure that will fclose it:

fopenlex(filename, mode)
   f := fopen(filename, mode);
   return (f, func() { fclose(f); } );

then in some other routine we can call fopenlex in some special way that causes the void(void) closure to automatically be treated the same as the =>-ified statement earlier. For example, maybe we assign it to a special operator:

   (f, =>) := fopenlex(filename, "r");

But while => is a really cute operator for the original scenario, it's incredibly ugly here. The symbol "_" is already used to mean "ignore this". Suggestions? I'm also open to things that don't involve assignment to a magical special symbol; we could just prefix 'fopenlex()' with an operator which means 'return the first element of this tuple, and =>-ify the second element of it', although that's obviously less flexible.

  • Post a new comment


    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded