Detecting at runtime when bindings go out of scope?

David Holz david.holz at grindwork.com
Fri Aug 26 03:13:01 UTC 2016


On 08/25/2016 06:20 PM, David McClain wrote:
> What I’m wondering about is being able to declare an item, a special 
> kind of Constructor parameter, which refers to a system resource that 
> needs scavenging, such that I could forego the WITH- formalism? Maybe 
> I’m asking for too much here… how would we ever detect the item being 
> stored? We’d need reference counting, and I tend to dislike that 
> approach very much..
>
> Anyone ever seen a system for resource reclamation that is better than 
> WITH- and UNWIND-PROTECT?
>
> - DM

If I'm understanding correctly, your ideal would be something like this:

(let ((channel (make-channel ...)))
   (do-stuff channel)
   (do-other-stuff channel))

and at the end of the lexical scope, due to the fact that the channel 
object has something special done to it during construction, it 
automatically calls disposal routines of the channel right at that point?

I think that's going to be tough, as well as ambiguous.  You don't want 
every lexical binding that happens to bind a channel object to destroy 
it at the end of the scope, a la (let ((ch (channel-slot-accessor obj))) 
...).  You want only those which "locally create" an object (by some 
distinguishable means) to destroy it at the end.  I personally think 
that would imply some form indicating a specific scope type that 
determines an object lifetime, which really does boil back down to 
with-* forms again. It is the scope itself that rules the object 
lifetime, not the other way around.

Examples from other languages would be C++ RAII (which is a usage style, 
not exactly an explicit feature), and Python's context managers.  I 
think the Python example would be the closest to a style that would fit 
a CL abstraction, and this is actually something I've thought about for 
quite some time.

This is off the cuff, but abstracting out the with-* style seems to boil 
down pretty neatly:

(defmacro scope (var creation-form &body body)
   `(let ((,var ,creation-form))
      (unwind-protect (progn , at body)
        (unscope ,var)))

(defgeneric unscope (obj))

So along with the standard construction form of an object, you'd define 
an UNSCOPE method for an instance of it, and the abstract (scope ch 
(make-channel ...) ...body...) should Just Work™.  It's still built on 
top of UNWIND-PROTECT, but you as the programmer need not worry about it 
yourself.

-- 
David Holz
Director, Grindwork Corporation
http://www.grindwork.com/




More information about the pro mailing list