From: "T. Onoma" Date: 2003-12-12T10:12:22+09:00 Subject: Re: Underpinnings of Method Wrapping On Thursday 11 December 2003 06:43 pm, Peter wrote: > I'll start changing all my "rescue SomeException => e" statements right > away! e-xcellent thinking. > > Oh, nice. And actually it can be easily done. We already have the ability > > to define a named layer of singleton via #extend. This actually creates a > > mixin on the singleton class. So the extending module remains a seperate > > entity from the singleton itself, and having a descernable name shoudl be > > fairly easy to manipulate/remove/replace. Good thinking, Peter! I like > > it. > > It's a better idea than what was originally in the back of my head: if > wraps have the same indicator, they belong to one layer, and you can > remove/redefine them based on indicator... But the new idea makes layers > more explicit, that's good! > Of course. But it would still bother me when there's one method that is a > very popular wrappee. Then you get a picture like this: > > w | | | | > r-m1-|--|--|-- > a | | | | > p-m2-m2-m2-m2- > p | | | | > e-m3-|--|--|-- > e | | | | > > So the wrappee has three methods m1, m2 and m3, and m2 is wrapped and each > time there is a new singleton layer. When calling m2, we need to go over > all the layers anyhow. But for m1 and m2 we wouldn't. Ideally we would > have this picture: > > w | > r----------m1- > a | > p-m2-m2-m2-m2- > p | > e----------m3- > e | > > So rather a chain of methods than a chain of layers. Unless of course you > would indicate shortcuts: > > w | | | | > r-m1---------- > a | | | | > p-m2-m2-m2-m2- > p | | | | > e-m3---------- > e | | | | > > Don't know if those pictures make sense. They do make sense, very good sense. And you make a good point. The problem is that each class is linked to the next, not each method. So overcoming the inefficiencies of picture #1 may prove a bit difficult. If no other way to circumvent presents itself, and assuming it is a signifficant performance loss, it may mean that the way inheritence currently works in Ruby needs to be improved to allow greater granularity, and thus work on a method by method basis rather than class by class. > Actually such a gc wouldn't make things much better. Wraps can > conditionally call super. Suppose a wrap does a security check and > decides you shouldn't call the method it wraps and raises an exception > instead. Looks right. Honestly I wouldn't want a gc of sorts anyway. > As for your way vs. the explicit wrap/redef way, I think either way there > is some ambiguity. But the latter allows the programmer to specify his > intention, and the Ruby interpreter can act accordingly. The programmer > can specify it wrongly, but Ruby shouldn't worry about that. Yes, and that goes both ways. From what I can thus far tell, this is simply a syntax matter with some "sytatical error" details attached. My way is more uniform, and thus I believe offers less inconsitencies, but alas it is less backward compatiable, and as you point out less explict (in the the same vain as class augmentations). So I think this is an issue we can leave for last, or until something comes up that makes a clear choice for us. I'm really not stuck on my way, as much as it might seem, its just I haven't yet seen another way that is in any way compelling. > > It's funny that this comes up, b/c I have started to think, in the back > > of my mind, that inner wraps --and by that I specifically means wraps > > that are flushed with the redefinition of the core method, are really of > > less use than I had orginally thought. > > Sorry, that's me putting subliminal messages in my mails... Yeeessss Maaaassster. > > Certainly a tangle to unravel here. I pray you can shed some clarity on > > this. > > Hey, you finally spelled clarity correctly :-) Clearly I have ;-) But please, no cracks on the spelling. I dispise it. And if I had my way, id prbly typ lk ths. > Anyway, I was thinking about the relation wrapping-subclassing. When we > make a subclass, and define a method that already exists, then there are > two cases: we call super in the new method or not. The same thing applies > to wrapping. So why is there no problem in the case of subclassing, and is > there a problem in the case of wrapping? Maybe it is because subclassing > explicitly adds a layer over the superclass, while wrapping currently does > not. So what if we look at wrapping as sneaking layers into the class > hierarchy? Such a layer would use the same syntax as subclassing. So if we > add a layer L to class C, that would be the same as adding a subclass L to > C, but everywhere where C is used, really L is used behind the scene. It > combines well with the new idea of layers. Exactly! That's exactly what I've been trying to convey. And is also exactly what tuned me on to my def syntax. (Guess I don't explain myself very well. Oh well.) Nonetheless, I'm glad you have envisoned this way of looking at it. It really made wraps make sense to me. And I see what you're saying about super. So, like subclasses, wrap should be perisistent, and it takes an explict undef to flush them, as they can always be cricumvented by not using super, but the may be gained back. > OK, but recall my example of a bidirectional link. We could have an aspect > do all the dirty work of maintaining the link and keeping it consistent. > We can't use module variables for this, because we need to keep the links > for a bunch of classes. Well, actually we can, but we'd need to keep > hashes that map objects onto their linked counterparts. But it's more > logical to store the links between two objects in those objects > themselves. But to understand that this is AOP, you'd need to let go of > the fact that AOP isn't all wrapping. Even AspectJ is not all about > wrapping. In AspectJ, it would look like this (don't count on my syntax > being correct though, I easily mix up syntax): > > class A {} > class B {} > > aspect BiDirLinkAB { > > private A B.linkToA = null; > // a link to B in class A, but class A can't see 'linkToA' > private B A.linkToB = null; > // a link to A in class B, but class B can't see 'linkToB' > > public void A.linkTo(B obj) { > if (linkToB) linkToB.linkToA = null; > // Note that although this method goes into class A, it can access > // linkToA in class B > linkToB = obj; > if (obj.linkToA) obj.linkToA.linkToB = null; > obj.linkToA = this; > } > > public void B.linkTo(A obj) { > // analogous > } > > public B A.getLinkToB() { > return linkToB; > } > > public A B.getLinkToA() { > return linkToA; > } > > } > > There's no wrapping, but it's cross-cutting since you have one entity (the > aspect) containing the code for maintaining data in two separate classes. Sorry, my java skills stink. As best I can make out, you're talking about a variable or method(?) particular to a class, but not visible to the class, but rather to the aspect that defines it. Sort of like a hash with an implied self.class for an index. @@private_to_aspect[self.class] If that about right? > > Already started-in on it. Give me a day or two. I am facing one problem > > though. Our use of the words inner and outer, up til now, have been a bit > > loose, either meaning tightly-linked and loosely-linked, or meaning > > non-persistent and persistent upon redef, respectively. So I'm not sure > > in which manner I should to give them a specific definition. > > I remember we had terms for both tightly/loosely linked and > (non-)persistence, but they never caught on. But if it really makes a > difference, we should try to consistently use different terms. I think its b/c persistence is a sticking point at the moment. Perhaps we should give some focus to this matter once again, starting with a review of what we've figured out about it thus far. Think I'll add some subsection note pages to the wiki page, this issue will be the first. Work for you? > > Wow. Can you tell me more about how that works? That's sounds quite > > interseting. What level of granularity do you mean? How does it work? > > I'll try, it's been a long time and Google can't find the website anymore > (I remember then it was the first hit I got, weird). But if you think > about it, optimizations are program transformations, and so is adding > wraps. The latter is less obvious in a language like Ruby, but one way to > look at AspectJ is that you describe the classes and the different > aspects, and they are really woven together to produce the complete, > full-fledged application. So that's the general idea of AOP: describe the > different aspects and how a code weaver can weave them together. Using > wraps is really just the tip of the iceberg, but the fact that AspectJ > uses that concept means that it is probably well understood at this > moment. > > But about optimizations... The example I remember is that of merging > loops. Suppose you have code like this: > > data.each do |d| > # process d, produce some data2 > end > # use data 2 > data.each do |d| > # process d, produce some data3 > end > # use data 3 > > So given some 'data', we use it in two subsequent calculations. We're > running over the data twice, but if we merge the loop, we do it just once: > > data.each do |d| > # process d, produce some data2 > # process d, produce some data3 > end > # use data 2 > # use data 3 > > However the two separate calculations are not entangled. For this simple > case, that may be less of a problem, but for realistic examples it can > turn out bad. What we then want to do is write the program as in the first > version, but indicate that the loops should be merged and write an aspect > that shows how to do it. > > data.each:merge do |d| > # process d, produce some data2 > end > # use data 2 > data.each:merge do |d| > # process d, produce some data3 > end > # use data 3 > > I used indicators by lack of something better :-) Showing how to merge the > loops is then done by giving a template: > > data.each:merge do || > > end > data.each:merge do || > > end > > produces > > data.each:merge do || > > > end > > This is just a rough idea, but what I read was such a rough idea. But also > this is a research area still. As for different in granularity; the above > is statement based, while wrapping is method based. Thanks. Is interesting, but does seem like a difficult undertaking. I can see why it is still research. > > Great. Although I'm not sure I understood what the misunderstanding > > is/was. But just the same, I certainly think we have come along way > > toward common understanding. > > /me thinks so too. Glad. T.