From: Timofei Shatrov
Subject: Redefining a method
Date: 
Message-ID: <43da1008.2524038@news.readfreenews.net>
Suppose there is a primary method as well as some around, before and
after methods. I need to redefine primary method and destroy all related
methods. There is no specialisation on parameters, so there is only one
instance of around, before and after method. Of course I can redefine
around method to (call-next-method) and before/after to always return
nil. But I guess there must be a better way.


-- 
|WAR HAS NEVER SOLVED ANYTHING|,----- Timofei Shatrov aka Grue---------.
|(except for ending slavery,  ||mail: grue at mail.ru ================ |
|   fascism and communism)    ||============= http://grue3.tripod.com  |
|...and Saddam's dictatorship |`----------------------------------[4*72]

From: Thomas A. Russ
Subject: Re: Redefining a method
Date: 
Message-ID: <ymihd7pr3ed.fsf@sevak.isi.edu>
····@mail.ru (Timofei Shatrov) writes:

> Suppose there is a primary method as well as some around, before and
> after methods. I need to redefine primary method and destroy all related
> methods. There is no specialisation on parameters, so there is only one
> instance of around, before and after method. Of course I can redefine
> around method to (call-next-method) and before/after to always return
> nil. But I guess there must be a better way.

While there are ways of doing this (See Pascal Costanza's answer), what
I would normally do in this situation is exit lisp, make the changes to
the source files, and then just reload everything.

Unless you really need to do this patch on a running system, I find this
to be a lot easier than hunting down the methods that need to be removed
and then removing them -- although an interface that showed all methods
and easily allowed them to be removed would certainly change that.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Zach Beane
Subject: Re: Redefining a method
Date: 
Message-ID: <m3d5ida5jr.fsf@unnamed.xach.com>
···@sevak.isi.edu (Thomas A. Russ) writes:

> ····@mail.ru (Timofei Shatrov) writes:
> 
> > Suppose there is a primary method as well as some around, before and
> > after methods. I need to redefine primary method and destroy all related
> > methods. There is no specialisation on parameters, so there is only one
> > instance of around, before and after method. Of course I can redefine
> > around method to (call-next-method) and before/after to always return
> > nil. But I guess there must be a better way.
> 
> While there are ways of doing this (See Pascal Costanza's answer), what
> I would normally do in this situation is exit lisp, make the changes to
> the source files, and then just reload everything.

When I first started using Linux, I accidentally unpacked a nethack
tarball in /dev. I couldn't figure out how to find and remove all
those files, so I just reinstalled Slackware.

> Unless you really need to do this patch on a running system, I find this
> to be a lot easier than hunting down the methods that need to be removed
> and then removing them -- although an interface that showed all methods
> and easily allowed them to be removed would certainly change that.

SLIME offers this:

   M-x slime-inspect #'method-name RET

Zach
From: Timofei Shatrov
Subject: Re: Redefining a method
Date: 
Message-ID: <43da6a99.7403460@news.readfreenews.net>
On 27 Jan 2006 09:23:22 -0800, ···@sevak.isi.edu (Thomas A. Russ) tried
to confuse everyone with this message:

>····@mail.ru (Timofei Shatrov) writes:
>
>> Suppose there is a primary method as well as some around, before and
>> after methods. I need to redefine primary method and destroy all related
>> methods. There is no specialisation on parameters, so there is only one
>> instance of around, before and after method. Of course I can redefine
>> around method to (call-next-method) and before/after to always return
>> nil. But I guess there must be a better way.
>
>While there are ways of doing this (See Pascal Costanza's answer), what
>I would normally do in this situation is exit lisp, make the changes to
>the source files, and then just reload everything.

I also discovered compute-applicable-methods, which is less kludgy than
find-method, but it still needs argument list to work.

>Unless you really need to do this patch on a running system...

The problem is, I need to do it at run-time. My project consists of main
library and user-supported modules. To load a different module I must
reload the library and then load that module. But previous module could
leave some "floating" methods, which won't be reset by a simple
reloading of the library. I probably would have to shadow defmethod with
my own one, which would register itself somewhere.

(cl:defmethod defmethod (&rest rest)
  `(push (cl:defmethod ,rest) *methods*))

But that probably doesn't work when the file is compiled. Do I need to
add eval-when somewhere?


-- 
|WAR HAS NEVER SOLVED ANYTHING|,----- Timofei Shatrov aka Grue---------.
|(except for ending slavery,  ||mail: grue at mail.ru ================ |
|   fascism and communism)    ||============= http://grue3.tripod.com  |
|...and Saddam's dictatorship |`----------------------------------[4*72]
From: Pascal Costanza
Subject: Re: Redefining a method
Date: 
Message-ID: <43vf5nF1pv0akU1@individual.net>
Timofei Shatrov wrote:
> On 27 Jan 2006 09:23:22 -0800, ···@sevak.isi.edu (Thomas A. Russ) tried
> to confuse everyone with this message:
> 
>>····@mail.ru (Timofei Shatrov) writes:
>>
>>>Suppose there is a primary method as well as some around, before and
>>>after methods. I need to redefine primary method and destroy all related
>>>methods. There is no specialisation on parameters, so there is only one
>>>instance of around, before and after method. Of course I can redefine
>>>around method to (call-next-method) and before/after to always return
>>>nil. But I guess there must be a better way.
>>
>>While there are ways of doing this (See Pascal Costanza's answer), what
>>I would normally do in this situation is exit lisp, make the changes to
>>the source files, and then just reload everything.
> 
> I also discovered compute-applicable-methods, which is less kludgy than
> find-method, but it still needs argument list to work.

compute-applicable-methods is not what you want - it is there to 
determine which methods are applicable for a given list of arguments. It 
may miss methods that are not applicable.

If your CL implementation supports the CLOS MOP you can see all the 
methods associated with a generic function with 
generic-function-methods. This is not in the common-lisp package though, 
so do an (apropos "GENERIC-FUNCTION-METHODS") to see in which package it 
is located.

>>Unless you really need to do this patch on a running system...
> 
> The problem is, I need to do it at run-time. My project consists of main
> library and user-supported modules. To load a different module I must
> reload the library and then load that module. But previous module could
> leave some "floating" methods, which won't be reset by a simple
> reloading of the library. I probably would have to shadow defmethod with
> my own one, which would register itself somewhere.
> 
> (cl:defmethod defmethod (&rest rest)
>   `(push (cl:defmethod ,rest) *methods*))
> 
> But that probably doesn't work when the file is compiled. Do I need to
> add eval-when somewhere?

defmethod is a macro, so you cannot redefine it with defmethod, but only 
with a new macro definition. However, most CLOS implementations don't 
provide enough rope to reimplement defmethod in the way you want.

Here is what you can do instead: In the library that you want to 
(re)load, add a (fmakunbound 'my-function) before the functions that you 
want to redefine. Then you can be sure that you start from a fresh 
generic function without any of the old methods defined on it.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: M Jared Finder
Subject: Re: Redefining a method
Date: 
Message-ID: <-K-dnYWZh60bU0fenZ2dnUVZ_sednZ2d@speakeasy.net>
Pascal Costanza wrote:
> 
<snip>
> Here is what you can do instead: In the library that you want to 
> (re)load, add a (fmakunbound 'my-function) before the functions that you 
> want to redefine. Then you can be sure that you start from a fresh 
> generic function without any of the old methods defined on it.

Do (generic) functions get garbage collected along with the rest of the 
data in most implementations?  Using fmakunbound would be my first guess 
to the OP's questions, but if functions don't get garbage collected, 
that would leave some (potentially huge) amounts of garbage accumulating.

   -- MJF
From: Pascal Costanza
Subject: Re: Redefining a method
Date: 
Message-ID: <44019iF1pknnvU1@individual.net>
M Jared Finder wrote:
> Pascal Costanza wrote:
> 
>>
> <snip>
> 
>> Here is what you can do instead: In the library that you want to 
>> (re)load, add a (fmakunbound 'my-function) before the functions that 
>> you want to redefine. Then you can be sure that you start from a fresh 
>> generic function without any of the old methods defined on it.
> 
> Do (generic) functions get garbage collected along with the rest of the 
> data in most implementations?  Using fmakunbound would be my first guess 
> to the OP's questions, but if functions don't get garbage collected, 
> that would leave some (potentially huge) amounts of garbage accumulating.

What makes you think they won't get collected?!?

Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: M Jared Finder
Subject: Re: Redefining a method
Date: 
Message-ID: <XLGdnTGsvY1peEfeRVn-tA@speakeasy.net>
Pascal Costanza wrote:
> M Jared Finder wrote:
> 
>> Pascal Costanza wrote:
>>
>>>
>> <snip>
>>
>>> Here is what you can do instead: In the library that you want to 
>>> (re)load, add a (fmakunbound 'my-function) before the functions that 
>>> you want to redefine. Then you can be sure that you start from a 
>>> fresh generic function without any of the old methods defined on it.
>>
>>
>> Do (generic) functions get garbage collected along with the rest of 
>> the data in most implementations?  Using fmakunbound would be my first 
>> guess to the OP's questions, but if functions don't get garbage 
>> collected, that would leave some (potentially huge) amounts of garbage 
>> accumulating.
> 
> 
> What makes you think they won't get collected?!?

Operating systems like to assume that executable code is unwritable. 
This would prevent Lisp from reusing the space the code was generated 
at, since it could no longer write to that executable space.

   -- MJF
From: Cameron MacKinnon
Subject: Re: Redefining a method
Date: 
Message-ID: <43dae9fb$0$15791$14726298@news.sunsite.dk>
M Jared Finder wrote:
> Operating systems like to assume that executable code is unwritable. 
> This would prevent Lisp from reusing the space the code was generated 
> at, since it could no longer write to that executable space.

And shall our operating systems serve us, or we them?

Dynamic linkers also write patches to code space. Just because most of 
the world believes in an edit -> disk -> compiler -> disk -> loader -> 
executable image cycle doesn't mean that generating code on the fly is a 
lost art.
From: M Jared Finder
Subject: Re: Redefining a method
Date: 
Message-ID: <FOydnfI8ieGFbUfenZ2dnUVZ_sSdnZ2d@speakeasy.net>
Cameron MacKinnon wrote:
> M Jared Finder wrote:
> 
>> Operating systems like to assume that executable code is unwritable. 
>> This would prevent Lisp from reusing the space the code was generated 
>> at, since it could no longer write to that executable space.
> 
> 
> And shall our operating systems serve us, or we them?
> 
> Dynamic linkers also write patches to code space. Just because most of 
> the world believes in an edit -> disk -> compiler -> disk -> loader -> 
> executable image cycle doesn't mean that generating code on the fly is a 
> lost art.

I'm worried about it becoming impossible.  For example, PaX, a Linux 
security patch, says:

The last feature of NOEXEC is the locking down of permissions on memory 
pages. This means that we prevent the creation of writable/executable 
file mappings (anonymous mappings are already made non-executable) and 
we also refuse to turn a writable or non-executable mapping into an 
executable one and vice versa. Since this lockdown breaks real life 
applications that do need to generate code at runtime, PaX allows to 
relax these restrictions on a per executable basis (along with other 
features).

While they acknowledge that not all applications can live with this 
restriction (Lisp definitely can't), I can imagine people not wanting to 
run executables that require disabling such a security feature.

   -- MJF
From: Pascal Bourguignon
Subject: Re: Redefining a method
Date: 
Message-ID: <87psmctxg2.fsf@thalassa.informatimago.com>
M Jared Finder <·····@hpalace.com> writes:
> I'm worried about it becoming impossible.  For example, PaX, a Linux
> security patch, says:
>
> The last feature of NOEXEC is the locking down of permissions on
> memory pages. This means that we prevent the creation of
> writable/executable file mappings (anonymous mappings are already made
> non-executable) and we also refuse to turn a writable or
> non-executable mapping into an executable one and vice versa. Since
> this lockdown breaks real life applications that do need to generate
> code at runtime, PaX allows to relax these restrictions on a per
> executable basis (along with other features).
>
> While they acknowledge that not all applications can live with this
> restriction (Lisp definitely can't), I can imagine people not wanting
> to run executables that require disabling such a security feature.

Depends on the kind of implementation.  clisp doesn't modify its
virtual machine.  All the compiled byte code is data as far as the OS
is concerned.  The joys of virtual machines! :-)


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush
From: Barry Margolin
Subject: Re: Redefining a method
Date: 
Message-ID: <barmar-39464E.01170128012006@comcast.dca.giganews.com>
In article <······················@speakeasy.net>,
 M Jared Finder <·····@hpalace.com> wrote:

> Pascal Costanza wrote:
> > M Jared Finder wrote:
> > 
> >> Pascal Costanza wrote:
> >>
> >>>
> >> <snip>
> >>
> >>> Here is what you can do instead: In the library that you want to 
> >>> (re)load, add a (fmakunbound 'my-function) before the functions that 
> >>> you want to redefine. Then you can be sure that you start from a 
> >>> fresh generic function without any of the old methods defined on it.
> >>
> >>
> >> Do (generic) functions get garbage collected along with the rest of 
> >> the data in most implementations?  Using fmakunbound would be my first 
> >> guess to the OP's questions, but if functions don't get garbage 
> >> collected, that would leave some (potentially huge) amounts of garbage 
> >> accumulating.
> > 
> > 
> > What makes you think they won't get collected?!?
> 
> Operating systems like to assume that executable code is unwritable. 
> This would prevent Lisp from reusing the space the code was generated 
> at, since it could no longer write to that executable space.

So?  All that matters in this discussion is whether the functions 
*logically* exist.  Whether the memory holding the code sequences are 
actually removed from the process memory is a transparent implementation 
detail, unless you have so many functions that you run out of virtual 
memory.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: ········@comail.ru
Subject: Re: Redefining a method
Date: 
Message-ID: <1138426377.631435.317650@g43g2000cwa.googlegroups.com>
Pascal Costanza wrote:

> M Jared Finder wrote:
> > Pascal Costanza wrote:
> >> Here is what you can do instead: In the library that you want to
> >> (re)load, add a (fmakunbound 'my-function) before the functions that
> >> you want to redefine. Then you can be sure that you start from a fresh
> >> generic function without any of the old methods defined on it.
> >
> > Do (generic) functions get garbage collected along with the rest of the
> > data in most implementations?  Using fmakunbound would be my first guess
> > to the OP's questions, but if functions don't get garbage collected,
> > that would leave some (potentially huge) amounts of garbage accumulating.
>
> What makes you think they won't get collected?!?

I think that specializer-direct-generic-functions will return even a
function, bound to an uninterned symbol.
From: Pascal Costanza
Subject: Re: Redefining a method
Date: 
Message-ID: <440t1iF1pkhfeU1@individual.net>
········@comail.ru wrote:
> Pascal Costanza wrote:
> 
>>M Jared Finder wrote:
>>
>>>Pascal Costanza wrote:
>>>
>>>>Here is what you can do instead: In the library that you want to
>>>>(re)load, add a (fmakunbound 'my-function) before the functions that
>>>>you want to redefine. Then you can be sure that you start from a fresh
>>>>generic function without any of the old methods defined on it.
>>>
>>>Do (generic) functions get garbage collected along with the rest of the
>>>data in most implementations?  Using fmakunbound would be my first guess
>>>to the OP's questions, but if functions don't get garbage collected,
>>>that would leave some (potentially huge) amounts of garbage accumulating.
>>
>>What makes you think they won't get collected?!?
> 
> I think that specializer-direct-generic-functions will return even a
> function, bound to an uninterned symbol.

You're right. I have just tested this (in Allegro, clisp, CMUCL, 
LispWorks, MCL, OpenMCL and SBCL), and only LispWorks seems to reliably 
remove a generic function from its specializers after an fmakunbound.

However, the following code is successful in all implementations:

(asdf:oos 'asdf:load-op :closer-mop)

(in-package :closer-common-lisp-user)

(defclass test () ())

(defmethod test ((test test))
   (print 'test))

(print :before)
(print (specializer-direct-generic-functions (find-class 'test)))
(print (specializer-direct-methods (find-class 'test)))

(loop for method in (generic-function-methods #'test)
       do (remove-method #'test method))
(fmakunbound 'test)

(print :after)
(print (specializer-direct-generic-functions (find-class 'test)))
(print (specializer-direct-methods (find-class 'test)))


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Duncan Harvey
Subject: Re: Redefining a method
Date: 
Message-ID: <1h9ua6t.sm7m5y1n4s5xiN%usenet-2006-01@abbrvtd.org.uk>
Thomas A. Russ <···@sevak.isi.edu> wrote:

> [Removing methods]
> 
> Unless you really need to do this patch on a running system, I find this
> to be a lot easier than hunting down the methods that need to be removed
> and then removing them -- although an interface that showed all methods
> and easily allowed them to be removed would certainly change that.

I don't think this helps the OP's particular case, but, for example, the
LispWorks IDE includes a generic function browser that makes it
straightforward to view and remove individual methods.

-- 
Duncan Harvey
From: Pascal Costanza
Subject: Re: Redefining a method
Date: 
Message-ID: <43ujesF1plrn2U1@individual.net>
Timofei Shatrov wrote:
> Suppose there is a primary method as well as some around, before and
> after methods. I need to redefine primary method and destroy all related
> methods. There is no specialisation on parameters, so there is only one
> instance of around, before and after method. Of course I can redefine
> around method to (call-next-method) and before/after to always return
> nil. But I guess there must be a better way.

See find-method and remove-method.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Coby Beck
Subject: Re: Redefining a method
Date: 
Message-ID: <F2SCf.154261$km.95144@edtnps89>
"Timofei Shatrov" <····@mail.ru> wrote in message 
·····················@news.readfreenews.net...
>
> Suppose there is a primary method as well as some around, before and
> after methods. I need to redefine primary method and destroy all related
> methods. There is no specialisation on parameters, so there is only one
> instance of around, before and after method. Of course I can redefine
> around method to (call-next-method) and before/after to always return
> nil. But I guess there must be a better way.

What you describe is probably the best way.  you could write a little 
utility:

(defmacro start-over (method class)
    `(progn
       (defmethod ,method :around ((,class ,class)) (call-next-method))
       (defmethod ,method :before ((,class ,class)) nil)
       (defmethod ,method :after  ((,class ,class)) nil)))

Handy for interactive development maybe...

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")