Ken MacLeod ken@bitsko.slc.ut.us
08 Sep 1998 14:06:03 -0500

"Fredrik Lundh" <fredrik@pythonware.com> writes:

> > One solution is to require calling a .destroy() (or
> >similarly-named) method when you're done with a node.  The method
> >would then do something like:
> >
> > def destroy(self):
> >     del self.parent
> >            for i in self.children:
> >         i.destroy()
> >     del self.children
> >
> >This is simple to implement, but it means that you have to remember
> >to call .destroy().  Does anyone see a representation that would
> >avoid the necessity of doing this?  I was thinking of just having
> >.children in each node, and then there would be a global dictionary
> >that mapped nodes to their parent objects.  Because it's global, it
> >wouldn't participate in any cycles, but cleaning it up is also a
> >pain.

> I definitely prefer the "destroy" pattern (or rather, I prefer to
> use visitors for this, but that's another story).

I've used a proxy-iterator to solve this problem and it seems to be
working well.

When you build the tree, don't include parent references.  But when
somebody asks for a tree object, return a proxy for the tree object
that includes a parent reference.  Create iterator methods in the
proxy object that return new proxies with a correct parent

The proxy-iterator classes are shadow classes for the object model
classes, so there's a one-to-one correspondence.  The tree objects end
up being simple data objects, it's the proxy-iterator that conforms to
the DOM interface.

For any ``active'' proxy-iterators, there will be a reference, but as
soon as the proxy-iterator is collected, the reference will go away,
leaving only the root of the tree as the primary reference -- release
the root and the entire tree is collected.

A side benefit of the proxy-iterator is that you can now share tree
fragments during processing, because the child-parent relationship is
contained in the proxy-iterator, not in the tree.

  Ken MacLeod