The problem is determining when they're no longer needed. To do this, it
seems like CLOS would have to use weak references for EQL specializers and
for references to methods in generic function object. That way, the
specializer won't prevent the object it specifies from being collected, and
the generic function's method table won't prevent the method from being
collected.
It's doable, but seems like lots of work for a situation that's extremely
uncommon. EQL specializers are usually used for long-lived things, such as
keywords or special cases of a generic function (e.g. if you had a
multiplication generic function, you might create methods specialized on
(EQL 0) and (EQL 1)). Leaving the unusable methods around shouldn't cause
any operational problems, and shouldn't have a performance impact if method
dispatch is implemented well (usually using a hash table).
--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
Marco Antoniotti <mar...@copernico.parades.rm.cnr.it> writes:
> Hi,
>
> I am working on a small application that potentially has a lot of code
> like
>
> (let ((zut (make-instance 'zot)))
> (defmethod meth ((z (eql zut))) #| do stuff |#)
>
> I know I can set up a macro WITH-INSTANCE-METHODS that did exactly
> what I want and added a bunch of unwind-protected REMOVE-METHODS at
> the end.
>
> However, wouldn't it be nice if the newly created methods were somehow
> colleted when the where no longer needed?
But that's why we have lambda and flet, because objects created with defun
stick around in the global environment. (Now I remember why I had thought
of generic-flet...) My guess is that generic-flet introduced too many
complications to be implemented efficiently, in terms of method lookup and
the like.
> Of course I have not really explored all the consequence of my
> desires. I suppose it may change the semantics of the language. Any
> thoughts about how an implementation may deal with this case?
I can't help but think... But why would you want to do something like this?
It seems like what you want is basically some data-directed
programming. Why not set up a hash table? You could have a method
specialize on class zot, and look up the hash table for an appropriate
lambda created at runtime. You would get everything you want with the
short-lived method approach you are thinking of, within relatively well
understood semantics of the language. (You would of course need two other
functions, one for creating dispatch lambdas, and the other for deleting
them.)
Or is there something you would miss out with this design?
Sunil
> In article <lw6780s...@copernico.parades.rm.cnr.it>,
> Marco Antoniotti <mar...@copernico.parades.rm.cnr.it> wrote:
> >
> >Hi,
> >
> >I am working on a small application that potentially has a lot of code
> >like
> >
> >(let ((zut (make-instance 'zot)))
> > (defmethod meth ((z (eql zut))) #| do stuff |#)
> >
> >I know I can set up a macro WITH-INSTANCE-METHODS that did exactly
> >what I want and added a bunch of unwind-protected REMOVE-METHODS at
> >the end.
> >
> >However, wouldn't it be nice if the newly created methods were somehow
> >colleted when the where no longer needed?
>
> The problem is determining when they're no longer needed. To do this, it
> seems like CLOS would have to use weak references for EQL specializers and
> for references to methods in generic function object. That way, the
> specializer won't prevent the object it specifies from being collected, and
> the generic function's method table won't prevent the method from being
> collected.
Or, I suppose you could write special code for the collector.
> It's doable, but seems like lots of work for a situation that's extremely
> uncommon.
I realize that it may be a lot of work. Maybe it will be an idea for
some tweaking of the CMUCL garbage collector(s).
> EQL specializers are usually used for long-lived things, such as
> keywords or special cases of a generic function (e.g. if you had a
> multiplication generic function, you might create methods specialized on
> (EQL 0) and (EQL 1)). Leaving the unusable methods around shouldn't cause
> any operational problems, and shouldn't have a performance impact if method
> dispatch is implemented well (usually using a hash table).
I agree with this - but only partially.
Cheers
--
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - 06 68 10 03 17, fax. +39 - 06 68 80 79 26
http://www.parades.rm.cnr.it/~marcoxa
> But that's why we have lambda and flet, because objects created with defun
> stick around in the global environment. (Now I remember why I had thought
> of generic-flet...) My guess is that generic-flet introduced too many
> complications to be implemented efficiently, in terms of method lookup and
> the like.
Does anyone who was there know why generic-flet &c were removed? It
seems to *me* that given the typical CLOS approach of computing stuff
(effective methods &c) on the fly and then caching agressively, things
like these are really hard to get right -- either you do the
computation each time (very slow), or you effectively have the things
lying around `secretly' all the time. This is especially bad for
WITH-ADDED-METHODS, which must almost by definition perturb the cache
of effective methods. But I'd like to know the real story!
--tim
To specialize a method for a specific instance doesn't make any
sense to me, but it does make sense to specify a subclass
for that instance, and specialize the method for the subclass.
And given one wants to use every obscure feature of CLOS,
you can then just use change-class to convert an instance
to the uniquely special class for the distinguished instance.
Or get serious, and call ensure-class to cons-up
a new subclass at runtime.
(class the-special-zot (zot))
(method meth ((z the-special-zot)) ...)
(let z = (make 'zot)
do
(change-class z 'the-special-zot)
)
Or another simpler way is to have a class slot for your
distinguished instance, and conditionalize the method on it.
(class zot (..)
(the-special-zot :initform nil :allocation :class)
)
(method meth ((z zot))
(if (eql (slot-value z 'the-special-zot) z)
then (my-most-special-zot-meth z)
else ..))
-Kelly Murray
But you still have to provide extra code in an UNWIND-PROTECT to delete
this singleton subclass and remove the method from the generic function.
The whole issue is wanting Lisp to realize that the extra method can be
garbage collected automatically.
See
<http://www.harlequin.com/education/books/HyperSpec/Issues/iss181-writeup.html>
for the X3J13 issue that removed them. The Discussion section contains
some of the rationale.
> Does anyone who was there know why generic-flet &c were removed?
Issue GENERIC-FLET-POORLY-DESIGNED in the CLHS speaks to the point.
See RPG's long comment towad the end of the writeup.
BM> See
BM> <http://www.harlequin.com/education/books/HyperSpec/Issues/iss181-writeup.html>
BM> for the X3J13 issue that removed them. The Discussion section
BM> contains some of the rationale.
The first paragraph of the writeup in the HS ("The current form of
lexical generic functiona is inadequate for general use, and therefore
there is no existing compelling reason to retain them.") has a typeo,
I think. Shouldn't "functiona" above be "functions"?
--
Rev. Dr. Xenophon Fenderson, the Carbon(d)ated, KSC, DEATH, SubGenius, mhm21x16
Pope, Patron Saint of All Things Plastic fnord, and Salted Litter of r.g.s.b
In a lecture, Werner von Braun once said "Ve haf alvays been aiming for zer
stars" and a little voice at the back replied "But ve keep hittink London".
Since the files in the HS were mechanically produced from the standard and
the X3J13 cleanup issues, that typo was probably in the original cleanup
issue. So the HS is presumably an accurate representation of what we voted
on.
> Good example for showing why EQL specializers can be eliminated.
No they cannot. They are a good idea brought into CL from various
"frame based" languages. The idea of 'instance' methods is good and I
believe useful (with limitations). Unfortunately, the "decoupling"
of methods over generic functions makes it tricky for the GC to work.
>
> To specialize a method for a specific instance doesn't make any
> sense to me, but it does make sense to specify a subclass
> for that instance, and specialize the method for the subclass.
> And given one wants to use every obscure feature of CLOS,
> you can then just use change-class to convert an instance
> to the uniquely special class for the distinguished instance.
> Or get serious, and call ensure-class to cons-up
> a new subclass at runtime.
>
> (class the-special-zot (zot))
>
> (method meth ((z the-special-zot)) ...)
>
> (let z = (make 'zot)
> do
> (change-class z 'the-special-zot)
> )
>
> Or another simpler way is to have a class slot for your
> distinguished instance, and conditionalize the method on it.
>
> (class zot (..)
> (the-special-zot :initform nil :allocation :class)
> )
> (method meth ((z zot))
> (if (eql (slot-value z 'the-special-zot) z)
> then (my-most-special-zot-meth z)
> else ..))
>
You are hand waving here. The method METH in your first example is not
collected. And in the second case you are special coding a lot of
stuff you really do not want to. On top of that you are not solving
the problem of:
(dotimes (i *qqq*)
(let ((x (make-instance 'x)))
(defmethod qwe ((y (eql x))) i)
(qwe x)))
I know it is an extreme case which you should work around, but it is a
problem which - I am conviced - should be dealt with by special code
in the GC.
Cheers
But it _should_ prevent the method from being collected, expect if the
specializer has died, so you need something more complicated. Also,
the method could die, if the gf has died, even if the specializer is
alive. LispWorks does pruning like this (for multi-methods and all
kinds of specializers), but only when tree-shaking; it's too
expensive.
--
Pekka P. Pirinen Harlequin Group plc, Cambridge, UK
A feature is a bug with seniority. - David Aldred <david_aldred.demon.co.uk>
> Barry Margolin <bar...@bbnplanet.com> writes:
> > The problem is determining when they're no longer needed. To do this, it
> > seems like CLOS would have to use weak references for EQL specializers and
> > for references to methods in generic function object. That way, the
> > specializer won't prevent the object it specifies from being collected, and
> > the generic function's method table won't prevent the method from being
> > collected.
>
> But it _should_ prevent the method from being collected, expect if the
> specializer has died, so you need something more complicated. Also,
> the method could die, if the gf has died, even if the specializer is
> alive. LispWorks does pruning like this (for multi-methods and all
> kinds of specializers), but only when tree-shaking; it's too
> expensive.
It seems to me that there are two differentissues here.
1 - is a GENERIC FUNCTION alive or not?
2 - is a method with EQL specializers invokable or not?
In case 1 I beleieve that you can remove the 'unbound' GF safely
(e.g. after a FMAKUNBOUND).
In the second case, apart form problems of 'constantness' (cfr. the
huge recent thread) it seems to me that this would just be an extra
pass in the garbage collector either using all the method objects as
roots or by setting up special gc tables rooted on objects
participating in EQL specializers. How much more expensive this would
be I do not know. But let's not kid ourselves. This is a problem of
reclaiming memory by tying together code and 'object' by 'object
identity'. Somehow it should be taken care of. As per the criteria
for collectability of a multi-method with EQL specializers, unless I
am missing something, you do away with the thing when one of the EQL
parameters has gone away.