... suppose you have a class (hierarchy) and a bunch of methods.
Now you want to add some before, after and around methods to your application. With a constraint: no new classes can be introduced, and, above all, user :before, :after and :around methods should work without modifications. I.e. suppose I have
I.e. How do I define the 'extra method' without clobbering the (zut :before (my-class)) one?
NB. The solution "define a method combination" does not seem to work because it'd require you to fix the method combination slot of the generic function. The "let's rewrite an :around method any time we do a define-extra-method" seems better, but I foresee problems regarding the definition environment and recompilation.
Anybody has some insight on this problem?
Kudos and cotillons to the person who figures out what I have been looking at in the past two days. :)
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
Marco Antoniotti <marc...@copernico.parades.rm.cnr.it> writes: > Anybody has some insight on this problem?
Why do you have a constraint that you can't add classes? This cripples you. If you're in a position to add methods, I'd think you'd be in a position to add classes... mostly.
And why do you have a problem adding additional methods? NORMALLY, only the person who maintains the code for a class should be adding methods to it. It's "impolite" to add methods to a class you don't maintain the defclass for, IMO. As such, if you own all the code, seems you're just saying "I want half the code in one form and half in another" and this problem reduces to the question:
I want to be able to do (defun foo () ...) and later (defun-also foo () ...) and I can't figure out how to jam two definitions into one function cell. That is, the problem isn't about CLOS at all, it's about distributed function definition.
My take on this is that you have overconstrained the problem. That doesn't mean there isn't an out, but it means you have to very carefully examine each of your constraints and you have to be pretty creative about what you can do in addition to what you might have said. For example, in the defun case, a possible solution is (defun-some foo () ...) (defun-some foo () ...) followed later by (ok-i\'m-done-defunning foo) And such a solution would work in the clos case, too.
The problem you're having is that you're trying to still exploit the "distributed definition" part of CLOS which relies on a shared model of "how to merge a new definition with a previous one" yet you haven't anywhere written code to do that merge. Moreover, you are neglecting that (method foo :after) amounts to a "name" in the sense that the CLOS method combination code does bookkeeping under this name and sees a further definition as a replacement of that name. If you want two "names" (two before methods), you need to make syntactic space for the CLOS code to hold the two names, or else you shouldn't be surprised that you can't wedge two definitions into the same mailbox. Either you have to modify the system itself or you have to use external storage, in which case you have to create a "time" when the seam-up is done (such as the ok-xxx operator I had above) or you have to maintain an auxiliary data structure so that every time a "definition" is done, the "real definition" is recreated from scratch from the contributed parts stored separately (which is what CLOS does).
This probably isn't the answer you wanted. But maybe it helps you understand the question you're asking.
>Why do you have a constraint that you can't add classes? >This cripples you. If you're in a position to add methods, >I'd think you'd be in a position to add classes... mostly.
>And why do you have a problem adding additional methods? >NORMALLY, only the person who maintains the code for a class >should be adding methods to it. It's "impolite" to add methods >to a class you don't maintain the defclass for, IMO. >As such, if you own all the code, seems you're just saying >"I want half the code in one form and half in another" and >this problem reduces to the question:
Actually, CLOS allows some relaxation of that impoliteness. If the generic function is part of your own application, I think you can feel free to define methods for someone else's classes. This is one of the great things about the fact that CLOS doesn't require pre-declaration of all the methods in the class specification (compare with C++'s class declarations). But if you're not the "owner" of the class or the GF, you shouldn't be adding methods.
That said, I have had to do the kinds of things Marco asks about in the past. When I was doing Lisp programming at Thinking Machines, we occasionally needed to customize the behavior of internal mechanisms on the Lisp system. We generally used the ADVISE mechanism; this isn't standard, but it was available in all the Lisp implementations we cared about (Symbolics and Lucid). This is essentially the "defun-also" mechanism that the original poster asked about.
-- 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.
Barry Margolin <bar...@bbnplanet.com> writes: > That said, I have had to do the kinds of things Marco asks about in the > past. When I was doing Lisp programming at Thinking Machines, we > occasionally needed to customize the behavior of internal mechanisms on the > Lisp system. We generally used the ADVISE mechanism; this isn't standard, > but it was available in all the Lisp implementations we cared about > (Symbolics and Lucid). This is essentially the "defun-also" mechanism that > the original poster asked about.
The only uses I know for advise are here there wasn't beforehand protocol cooperation, which doesn't sound like it's the lay of the land here.
I usually use other devices for things that some people would do this defun-also thing. e.g.,
I like this kind of approach because both parties have to acknowledge their involvement in the cooperation and because it doesn't involve any prior knowledge by A of B, but B also doesn't affect A's code--only A's data. I know people that prefer to use ADVISE for this, but I really don't like that. Of course, one can macrofy this.
I agree with much of Kent's reply, that essentially you're asking to put multiple things in a box that only holds one thing, i.e. it's the same as asking to have multiple code for a function, where a function has only one code. Of course, CLOS methods are exactly this capability relative to function, you CAN add more code to one generic function. That said, the typical way to have "system" code not interact with "user" code for a method is to define an internal method that is called which the system code (or user code) extends.
I do this for the NiCORE persistent object system, by having a initialize-persistent-instance method that the system extends, leaving the user to extend initialize. In your case, you must do it the other way because the system wasn't designed for user extension:
(defmethod zut :around ((c my-class)) (zut-extra-before c) (call-next-method) (zut-extra-after c) )
;; excuse the silkscript syntax..
(macro define-extra-method (name when args [body]*) (if (eq when :before) then `(method {(new-symbol name '-extra-before)} :before {args} {body}*) elseif (eq when :after) then `(method {(new-symbol name '-extra-after)} :after {args} {body}*) else ;; pick before or after `(method {(new-symbol name '-extra-after)} {args} {body}*) ))
> ... suppose you have a class (hierarchy) and a bunch of methods.
> Now you want to add some before, after and around methods to your > application. With a constraint: no new classes can be introduced, and, > above all, user :before, :after and :around methods should work > without modifications. I.e. suppose I have
> I.e. How do I define the 'extra method' without clobbering the > (zut :before (my-class)) one?
> NB. The solution "define a method combination" does not seem to work > because it'd require you to fix the method combination slot of the > generic function. > The "let's rewrite an :around method any time we do a > define-extra-method" seems better, but I foresee problems regarding > the definition environment and recompilation.
> Anybody has some insight on this problem?
> Kudos and cotillons to the person who figures out what I have been > looking at in the past two days. :)
Marco Antoniotti <marc...@copernico.parades.rm.cnr.it> writes: > Kudos and cotillons to the person who figures out what I have been > looking at in the past two days. :)
an implementation of a parallel computation model (eg., a hardware description language)?
> I.e. How do I define the 'extra method' without clobbering the > (zut :before (my-class)) one?
A (implementation specific/MOP dependent) way of doing this might be to get the function object corresponding to the original :before method. I imagine it would then be relatively simple to enclose that object around a fresh definition of a :before method, letting you hold on to all prior methods.
I can think of two broad categories where this comes up:
I. Design for open implementation. If you're designing an application that you want users to be able to extend and customize, then THEY will be under the constraints you give, but YOU will not. YOU can define additional classes and/or methods. The common techniques are: A. Sprinkle dummy mixin classes into public ones. This gives you a place to hang new methods in patches, etc. A typical arrangement is: (defclass FOO (custom-foo foo-implementation) ()) where the implemenation hangs its methods on foo-implementation. B. Layer the major public methods with subprotocols. As in the AMOP, you will need to tell the user which methods can be overwritten or extended, where extension is defined as something that still calls the implementation's method. C. Have your implementation call internal methods, which are layered, and only document the things that it calls. This gives you room to to specialize your code, while leaving the users to specialize the public stuff.
None of these help you where there is more than one independent body which wants to be able to separately make customizations/patches which can be simultaneously loaded. For this I think you need some formalization of the following...
II. Hacking an existing implementation. Here the restrictions may really be on you. In addition to ADVISE, if available, remember that if the CLOS MOP is available to you, you can write code which, at compile time, locates currently existing applicable methods, grabs their method-functions, and calls them explicitly within the body of the new method. You can glomm together as much as you want this way. Be careful, though, if you want to be able to reload such code (i.e. load it more than once), then you'd better find a way to keep track of which existing methods you're replacing, and making sure you don't call yourself as many times as you have reloaded the code. DEFVAR is your friend.
> ... suppose you have a class (hierarchy) and a bunch of methods.
> Now you want to add some before, after and around methods to your > application. With a constraint: no new classes can be introduced, and, > above all, user :before, :after and :around methods should work > without modifications. I.e. suppose I have
> I.e. How do I define the 'extra method' without clobbering the > (zut :before (my-class)) one?
> NB. The solution "define a method combination" does not seem to work > because it'd require you to fix the method combination slot of the > generic function. > The "let's rewrite an :around method any time we do a > define-extra-method" seems better, but I foresee problems regarding > the definition environment and recompilation.
> Anybody has some insight on this problem?
> Kudos and cotillons to the person who figures out what I have been > looking at in the past two days. :)
> > I.e. How do I define the 'extra method' without clobbering the > > (zut :before (my-class)) one?
> A (implementation specific/MOP dependent) way of doing this might be to get > the function object corresponding to the original :before method. I imagine > it would then be relatively simple to enclose that object around a fresh > definition of a :before method, letting you hold on to all prior methods.
The problem here is that you need a way of accomodating redefinition. It may or may not be apparent, but the entire language is organized around the idea that you might need to re-evaluate any definition in isolation in an interactive editor. That's impossible to assure in general because there is an order-of-evalution issue that can't be escaped when top-level executable forms are present, but my point is that if what you're encouraging is the idea that it just do (setf (symbol-function symbol) (functionally-encapsulate new (symbol-function symbol))) or the equivalent, the problem is that you're making it very dependent on load order in a way that CLOS is not. That doesn't mean it can't work that way, but it's more fragile. It also means that re-evaluating a lone definition risks having the function called twice.
Then again, my recollection is that the lisp machine uses a scheme similar to what it sounds to me like you're proposing. In that model, there is an object that can live in a function cell which is an "encapsulation" so that in addition to wrapping new definitions around old ones, you can, for example, also notice that an existing definition is encapsulated and decide to remove the 2nd innermost encapsulation leaving the others in place. This is used for tracing, advising, and other things that share a common value cell. But it pretty much relies on the introspective leverage offered by saying that the encapsulation is a first-class inspectable/manipulable object with data components you can read and modify rather than just a black box that you can funcall like CL functions basically are.
Disclaimer: I'm being slightly vague in the first paragraph above because I'm not 100% sure I understood your suggestion and that I'm responding to what you actually said. I'm being slightly vague in the second paragraph because my memory of the lispm functionality is potentially faulty and I'm too lazy to move to the chair next to me to poke around on my macivory and find out for sure.
> > A (implementation specific/MOP dependent) way of doing this might be to get > > the function object corresponding to the original :before method. I imagine > > it would then be relatively simple to enclose that object around a fresh > > definition of a :before method, letting you hold on to all prior methods.
> The problem here is that you need a way of accomodating redefinition. > It may or may not be apparent, but the entire language is organized > around the idea that you might need to re-evaluate any definition > in isolation in an interactive editor. That's impossible to assure > in general because there is an order-of-evalution issue that can't > be escaped when top-level executable forms are present, but my point > is that if what you're encouraging is the idea that it just do > (setf (symbol-function symbol) > (functionally-encapsulate new (symbol-function symbol))) > or the equivalent, the problem is that you're making it very dependent > on load order in a way that CLOS is not. That doesn't mean it can't > work that way, but it's more fragile. It also means that re-evaluating > a lone definition risks having the function called twice.
Good point, this would most certainly be dependent on load order. But then, going back to what Marco had originally asked:
> > > I.e. How do I define the 'extra method' without clobbering the > > > (zut :before (my-class)) one?
It would appear that ensuring a general, fool-proof approach of doing this sort of thing with :before methods is going to be very difficult. What I had proposed was a simple hack to get it working.
I'll try to address your objections, as I understood them:
1. If another :before DEFMETHOD with the same specializers is evaluated, the existing method along with all the extra-methods should vanish. We would be replacing the old definition (along with all the nexted closures) with the new definition. At least I find this behavior intuitive. The alternative is to have the extra-methods hang around irrespective of the current definition of the :before method. I'm sure this could be done by hacking into the MOP, but there might be an easier way (below).
2. The behavior of define-extra-method, as Marco has described it, is more like an advice form, and as such *should* be order dependent. There is no specification here as to the order in which the extra-methods should execute. Indeed, there is not even a mechanism to identify them uniquely, which would make it very difficult to redefine one particular extra method if it is misbehaving.
I wholly agree that these restrictions would get in the way of flexibly interacting with and debugging the functions. The best way to get around this would be to attempt a method combination.
I have never had the need to define a method combination, so what I am proposing might be severely broken. I'm going by my understanding, rather than any implementation experience.
My interpretation of method combinations is that CHAIN can be written to generate a combination that collects multiple :before methods and executes them all. The method definition rules at the same time should ensure that the :before methods do not get redefined unless the reason matches. The primary method will be one without a reason attached. This should address all the problems the original proposal had. (If I had the time, I'd have written some sample code and tested it out. Unfortunately...)
Sunil Mishra <smis...@whizzy.cc.gatech.edu> writes: > I wholly agree that these restrictions would get in the way of flexibly > interacting with and debugging the functions. The best way to get around > this would be to attempt a method combination.
or adopt a naming strategy in which the name *does* imply ordering, which is what the class precedence list does. that's why, incidentally, the cpl is totally ordered--to avoid variances in effect due to porting. it's not conceptually necessary, but it's a real mess in practice if it's not fully ordered. and that's also why when this question was first raised my question was "why disallow class definition" because simply subclassing (or "superclassing"--that is, interposing a hidden class above the published class) and putting the new method on the other class would allow someone who controlled the sources to the class to also write the code in a way that was not perturbed by load order. class inheritance order is a de facto engineering solution to this, and you're working with your hands tied behind your back when you disallow it.
I never used this syntax, but I'm pretty sure a series of non-lists is the qualifiers. That is, (defmethod zut chain :before for-some-reason ((c my-class)) ...) Even then, unless you order them alphabetically or have a priority scheme you still have an ordering problem that subclassing avoids (because "subclassp" is an ordering predicate, not because of magic).
> The hard part with any priority scheme is that usually it ends up based > on numbers. And numbers are stupid. They let you deterministically > order, but they mean nothing and so don't give you any conceptual leverage > over the problem space. Ideally you'd like to be able to do something like: > (defmethod zut chain :before :call-me fred :must-follow bill ((c my-class)) > ...) > but the problem there is that the :must-follow is meta-information not related > to the name, and if you have to change the ordering to say > :must-follow mary > clos would think you had added a new method, not changed an existing one, > because it does not distinguish qualifiers for naming purpose from qualifiers > as omittable attributes.
Agreed. Having been in AI type research this long has given me ample reason to doubt the power of numbers :-) The priority scheme would have to have the ordering defined independently of the methods. I don't think it would work any other way. Numbers are good in the sense that the priorities are independent of the situation. We could construct a non-numerical approach for which this is true... I'm thinking along the lines of:
(defmethod zut chain :before fred ((c my-class)) ...)
(deforder fred bill)
or some such. This should allow for changes in the priority mechanism independent of the method definitions.
> The mechanism CLOS provides, for better or worse, > that does allow you to manage names in partial orders and composition of > partial code fragments based on those partial orders is the class structure > itself. I really recommend either coming to grips with that or rethinking > the need to have these multiple definitions or implementing these multiple > definitions with new meta-linguistic stuff rather than trying to shoehorn > it into parts of the language not intended for that purpose.
I don't really need any of this, it's been more of a mental game for me :-) I would hate to have to deal with the complexity of implementing this elaborate a scheme. I was simply looking for ways of doing it at the method or generic function level rather than playing with the class structure.
Issues of efficiency, flexibility etc. would have to be resolved at the application level, so I guess it would be up to Marco to sort out the mess.
> > I wholly agree that these restrictions would get in the way of flexibly > > interacting with and debugging the functions. The best way to get around > > this would be to attempt a method combination.
> or adopt a naming strategy in which the name *does* imply ordering, > which is what the class precedence list does. that's why, incidentally, > the cpl is totally ordered--to avoid variances in effect due to porting. > it's not conceptually necessary, but it's a real mess in practice if > it's not fully ordered. and that's also why when this question was first
Yes, I realize that, and was quite impressed with the attention to detail when I read about it in AMOP.
> raised my question was "why disallow class definition" because simply > subclassing (or "superclassing"--that is, interposing a hidden class above > the published class) and putting the new method on the other class would > allow someone who controlled the sources to the class to also write the > code in a way that was not perturbed by load order. class inheritance > order is a de facto engineering solution to this, and you're working with > your hands tied behind your back when you disallow it.
There are some issues with subclassing that a method combination would avoid, as I see it.
1. The proliferation of classes might not be desirable.
2. Subclasses are being used not to distinguish between types of data that are genuinely different. It is rather being used for obtain an effect in the methods you can define. A method combination would make this more obvious.
3. I'm not clear on what class you would make an object belong to. If you made an object a subclass of my-class, then creating subclasses of my-class for the purpose of method ordering would fail. If you defined my-class as a subclass of a set of classes on which you define the other methods, I imagine efficiency might become an issue. Further, you would need to provide the user with the ability to add a class at run-time if this type of ordering is to be part of the exported interface.
4. You would have to go ahead and define all those superclasses for any class on which you want this kind of behavior. With method combinations you would be able to restrict this behavior to specific generic functions rather than enforcing it across all generic functions.
> I never used this syntax, but I'm pretty sure a series of non-lists > is the qualifiers. That is, > (defmethod zut chain :before for-some-reason ((c my-class)) ...)
Hmmm, that would make more sense. I was trying to figure out with the syntax I had presented how defmethod might differentiate the combination from the argument list.
> Even then, unless you order them alphabetically or have a priority > scheme you still have an ordering problem that subclassing avoids (because > "subclassp" is an ordering predicate, not because of magic).
Yes, but a priority scheme would not be that hard to add in. It is potentially expensive though, if for each invocation you have to sort out the priorities. And it would most definitely be more work than subclassing.
Sunil Mishra <smis...@cleon.cc.gatech.edu> writes: > 2. Subclasses are being used not to distinguish between types of data that > are genuinely different. It is rather being used for obtain an effect in > the methods you can define. A method combination would make this more > obvious.
> 3. I'm not clear on what class you would make an object belong to. If you > made an object a subclass of my-class, then creating subclasses of > my-class for the purpose of method ordering would fail. If you defined > my-class as a subclass of a set of classes on which you define the other > methods, I imagine efficiency might become an issue. Further, you would > need to provide the user with the ability to add a class at run-time if > this type of ordering is to be part of the exported interface.
I'd want to see an actual worked example with non-contrived names before believing this wasn't going to work, both for efficiency reasons and for conceptual reasons. As a rule, I don't think CLOS causes a speed penalty when the method is inherited from a superclass. I think the speed is identical in the case where you say you imagine efficiency would be an issue, but absent a real example, i can't be sure.
> 4. You would have to go ahead and define all those superclasses for any > class on which you want this kind of behavior. With method combinations > you would be able to restrict this behavior to specific generic > functions rather than enforcing it across all generic functions.
If method combination works, I'm not saying not to use it. But if it's not working, I'm saying the reason it's probably not is that you're expecting something to happen by magic.
> > I never used this syntax, but I'm pretty sure a series of non-lists > > is the qualifiers. That is, > > (defmethod zut chain :before for-some-reason ((c my-class)) ...)
> Hmmm, that would make more sense. I was trying to figure out with the > syntax I had presented how defmethod might differentiate the combination > from the argument list.
> > Even then, unless you order them alphabetically or have a priority > > scheme you still have an ordering problem that subclassing avoids (because > > "subclassp" is an ordering predicate, not because of magic).
> Yes, but a priority scheme would not be that hard to add in. It is > potentially expensive though, if for each invocation you have to sort out > the priorities. And it would most definitely be more work than subclassing.
The hard part with any priority scheme is that usually it ends up based on numbers. And numbers are stupid. They let you deterministically order, but they mean nothing and so don't give you any conceptual leverage over the problem space. Ideally you'd like to be able to do something like: (defmethod zut chain :before :call-me fred :must-follow bill ((c my-class)) ...) but the problem there is that the :must-follow is meta-information not related to the name, and if you have to change the ordering to say :must-follow mary clos would think you had added a new method, not changed an existing one, because it does not distinguish qualifiers for naming purpose from qualifiers as omittable attributes. The mechanism CLOS provides, for better or worse, that does allow you to manage names in partial orders and composition of partial code fragments based on those partial orders is the class structure itself. I really recommend either coming to grips with that or rethinking the need to have these multiple definitions or implementing these multiple definitions with new meta-linguistic stuff rather than trying to shoehorn it into parts of the language not intended for that purpose.
Somehow I had a hunch that method combination could do the (or at least some) of the trick. However, I am not so sure that it would completely clear the issues. As it was pointed out, there are two main sources of problems.
1 - Everything should be "redefinable". 2 - You do not have access to the actual method <body code>.
I kind of believe that, if not the full MOP, at least some introspection into the <body code> of a method would be very useful. Something like
METHOD-BODY method => code object
Where code object is an immutable opaque structure which could be combined - at least - in a PROGN like form, with something like
Anyway, this may be asking too much; just like the encapsulation machinery described by KMP.
All in all, I'd settle for the following scheme (I am veering off a tangent here...) which, I believe, solves some of the problems of Sunil's :must-follow, DEFORDER proposal.
Right now we can call a single :before or :after method. I'd like a method combination that could call a set (i.e. an ordered list) of (:before :after) methods with the following specification (allow me not to call it a 'method-combination')
In the first case the :before (:after) method is guarateed to be added first in the set of :before (:after) methods applicable in a given method call. The second case is the symmetric one: the method is guaranteed to be added last. Of course this introduces a "load eval compile" order problem, but I presume it is something that can be lived with. The key here is that any "current" :before (:after) method does not get clobbered.
The third case is the more interesting.
First of all let me note that I can rewrite all "standard" :before and :after method definitions as
(defmethod zut :before t (<method lambda list>) ...)
why will become clear in a sec.
This form tells me to order the set of :before and :after methods applicable to a given actual <method lambda list> according to the CPL of <class>. In particular, when two methods insist on the same <class> (i.e. the case with 't') the second method defined clobbers the first; as it happens now. I.e.
(defmethod zut :before t ((s symbol)) 1)
(defmethod zut :before t ((s symbol)) 2)
Will result in the call (zut 'foo) to return 2.
Let's see an example
(defclass zot ....)
(defmethod something-about-zot ((z zot)) ...)
;;; Let's add some debugging
(defmethod something-about-zot :before :first ((z zot)) (format t ">>> ZOT debugging: calling SOMETHING-ABOUT-ZOT with ~S.~% z))
;;; and let's add some locking machinery to the class ZOT, on ;;; operation SOMETHING-ABOUT-LOCK.
In this case I do not really care about the order of execution of the debugging code and of the locking code. I just care that they get both executed on operation SOMETHING-ABOUT-ZOT when called on a ZOT instance.
Soppose I decide that debugging and locking must be executed in order.
Now I have the guarantee that debugging and locking code will be execute according to the CPL of the classes mentioned in the definitions.
How you'd compile this, I have no idea. It almost looks like that the "add method" procedure would become a O(n^2) operation, but I am just guessing here.
I do not even have an idea whether you could implement this as a METHOD-COMBINATION (which would require you to declare all you generic functions as having that particular method combination, which is a no-no in my idea of how thing should be done.
Now, what are the advantages of this scheme.
First of all, IMHO, it is CLOS like.
Second, it does not require you to either (a) change the "original" class hierarchy in order to accommodate the new operations you may add as :before or :after methods and (b) it allows you to keep all your "extra" code separated and organized according to intent or to the "aspect" (this is the keyword :) ) you want to deal with.
Finally, I am indebted to Barry Margolin for his suggestion to look into Gregor Kiczales' "aspect oriented programming". Two days reading their papers and playing around with AspectJ made me waste some more time thinking about these issues in CL. http://www.parc.xerox.com/spl/projects/aop
Of course there is much more under the stars, than what can be contained between two parenthesis :)
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
>>>>> "Kent" == Kent M Pitman <pit...@world.std.com> writes:
Kent> ... Kent> NORMALLY, only the person who maintains the code for a class Kent> should be adding methods to it. It's "impolite" to add methods Kent> to a class you don't maintain the defclass for, IMO. Kent> ...
ITOOGK (In The Opinion of Gregor Kiczales :-), there can be times and places where moving in on the domain of a library both is usefull and manageable, provided one adheres to some basic rules.
This is described and analyzed in a paper called
Issues in the Design and Specification of Class Libraries
---------------------------+----------------------------------------------- --- Christian Lynbech | Telebit Communications A/S Fax: +45 8628 8186 | Fabrikvej 11, DK-8260 Viby J Phone: +45 8628 8177 + 28 | email: c...@tbit.dk --- URL: http://www.telebit.dk ---------------------------+----------------------------------------------- --- Hit the philistines three times over the head with the Elisp reference manual. - peto...@hal.com (Michael A. Petonic)
after some dreams during the night and a check on the DEFINE-METHOD-COMBINATION spec. I believe that the sort of Aspect Based Programming I described in my previous post can be very easily implemented and - above all - integrated in CL.
A couple more days (after CODES99) and I'll be back with something. :)
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
Christian Lynbech <c...@tbit.dk> writes: > >>>>> "Kent" == Kent M Pitman <pit...@world.std.com> writes:
> Kent> ... > Kent> NORMALLY, only the person who maintains the code for a class > Kent> should be adding methods to it. It's "impolite" to add methods > Kent> to a class you don't maintain the defclass for, IMO. > Kent> ...
> ITOOGK (In The Opinion of Gregor Kiczales :-), there can be times and > places where moving in on the domain of a library both is usefull and > manageable, provided one adheres to some basic rules.
> This is described and analyzed in a paper called
> Issues in the Design and Specification of Class Libraries
Yep. Very good arguments indeed. Of course there are no numbers to support this, but I'd say that (although it may not be the case for CL) "reuse" and "legacy" are buzzwords that do get in the way of the "one class <-> one maintaner" (and I'd add one ``use'') rule.
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
On 03 May 1999 14:41:14 +0200, Marco Antoniotti wrote:
>after some dreams during the night and a check on the >DEFINE-METHOD-COMBINATION spec. I believe that the sort of Aspect >Based Programming I described in my previous post can be very easily >implemented and - above all - integrated in CL.
Hey. Again that aspect stuff...
I was reading iX yesterday and noticed an article about a new idea in Java: Aspects, i.e. :before and :after methods. I'm stunned.
Did I miss something or is this just old wine in new bags?
Groetjes, Peter
-- It's logic Jim, but not as we know it. | pvane...@debian.org for pleasure, "God, root, what is difference?",Pitr | pvane...@inthan.be for more pleasure!
> I was reading iX yesterday and noticed an article about a new idea in > Java: Aspects, i.e. :before and :after methods. I'm stunned.
> Did I miss something or is this just old wine in new bags?
Well, Gregor Kiczales decided, that what is good for Common Lisp, is even better for other languages (in the sense that they need it much more ;), and so decided to persue many of his ideas with Java (see the Xerox Parc website[1], especially the Open Implementation and Aspect Oriented Programming topics). Of course with Java, you need to invent a new language to specify the "other aspects", whereas Lisp is strong enough a foundation, that you can do it using the same language (see e.g. method combinations, etc.).
So his ideas may get more of a hearing in the "Real World(tm)", OTOH we will probably have to do our implementation of AOPs on our own ;)
> pvane...@mail.inthan.be (Peter Van Eynde) writes:
> > I was reading iX yesterday and noticed an article about a new idea in > > Java: Aspects, i.e. :before and :after methods. I'm stunned.
> > Did I miss something or is this just old wine in new bags?
> Well, Gregor Kiczales decided, that what is good for Common Lisp, is > even better for other languages (in the sense that they need it much > more ;), and so decided to persue many of his ideas with Java (see the > Xerox Parc website[1], especially the Open Implementation and Aspect > Oriented Programming topics). Of course with Java, you need to invent > a new language to specify the "other aspects", whereas Lisp is strong > enough a foundation, that you can do it using the same language (see > e.g. method combinations, etc.).
There is a little more to it than just :before and :after methods. In particular, I really liked Cristina Videira Lopes' thesis. There is quite a bit of of survey and motivation that go beyond the simple introduction of auxiliary nethods. In particular, there is the problem of "inheritance anomalies" which needs to be taken into account.
> So his ideas may get more of a hearing in the "Real World(tm)", OTOH > we will probably have to do our implementation of AOPs on our own ;)
It's coming! :) I just realized that maybe it could be done with method combination. With such a foundation the implementation of all of AspectJ is very short.
BTW. What name do you like? CLAP (CL Aspect Programming) or Hackspect? :)
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