From: "T. Onoma" Date: 2003-12-01T03:10:01+09:00 Subject: Re: Underpinnings of Method Wrapping On Sunday 30 November 2003 03:57 pm, Peter wrote: > I like the proper separation, but why pre and post for extrinsic and def > wrap for intrinsic? Hmm, not sure how you're asking. Why different keywords? Or why different use? I'll just spell out in detail: I think that pre and post are different enough from def to warrant there own distinct keywords becuase pre and post can't change the method parameters or alter the return value, which def can. def eat(x) return x end def eat(x) x.pop x = super return x << "BREAD" end pre eat print "I can't change the fact that I'm being told to eat #{x}." end post eat print "Nor say I did otherwise, as I also eat some #{x.last}." end Notice that the parameters are not required for pre and post since they can't alter anything about the def, only "observe". (Actually I'm not sure what the plan on pre and post parameters is.) Its not a big deal really, just makes the syntax a little cleaner perhaps. defpre, def_pre, predef, pre_def, etc. any of them would work as well. > Yup, the call stack in general is pretty small, except in case of a > recursive algorithm. But mutually recursive methods complicate things a > bit for any shortcut ;-) eew, that could bite. > > I noticed right away that you were using my syntax :-) I've heard so many > > people say how ridiculous such a syntax is (funny that they keep > > mentioning it), but right now I can tell you it feels completely natural > > --seeing the defs come in order parallels their stacking order. Anyway... > > Agreed, but these are small examples. What if a primary method and its > wraps are dispersed throughout the source code? Realize that your only saving yourself from distingusihing a single layer of wraps. After that you're back to the same thing anyway: def eat(x) return x end defwrap eat(x) x.pop x = super return x << "BREAD" end defwrap eat(x) x = super return x << "WINE" end You've only mangaged to defer the issue one step, while adding extra syntax in the process. One might argue that the first layer is the most common case, but is that really compelling enough? Perhaps it is when combined with 100% back compatability. But I think the more uniform syntax is worth it. The cases in which it does back break compability, the fix is so simple, a patch tool could be easy written to fix all such code automatically. Also realize that not using the more uniform case means more variations the interpretor must account for (i.e. a wrap is given but no def, etc.) Even so, I'm not going to make a big stink about it either way. There are more important issues to ensure make it into future Ruby AOP, such as super wrapping and indicator tags and all the other stuff we've been talking about. > > Definitely, and I'm certain we can achieve the same thing with module's > > and their instance variables. Define a module containing aspect methods > > and the module variables they need and apply as desired. Hell, we can > > even wrap the aspect methods! > > > :-) But one aspect adding advice to methods in more than one class is - > though perfectly possible - more complicated, unless I'm overlooking > something obvious. Considering you could hit every thing up using Object, plus common Mixins like Enumberable. That goes a long way. No doubt to be selective, well, you have to be selective one way or another. Right? So I'm not sure how you can do otherwise anyway. You have a specific notion in mind? > > Ah...but this is what the indicators are for. > > > > def eat:eating > > end > > > > def gorge:eating > > end > > > > def stuffyourface:eating > > end > > > > We can aspect all the eating methods. ( no, i'm not hungry :-) > > Grand! Can we specify multiple indicators when calling multiple methods > with different indicator demands? Just to be clear, the indicators are just "tags", one still calls the method using just #eat, for instance. So if your asking can we do: def eat:eating:consuming .. end I'd don't see why not (an array of indicators?) But keep in mind you can always do pattern matching on the symbol: method(eat).to_s.tag =~ /consuming/ So I don't know if we really need to do beyond a single indicator symbol. > Ah, that kind of singletons... But it confuses me that you are calling the > method the singleton. Isn't c the singleton, with its own singleton class > in which the method x is put? Sorry. I use it both ways: A singleton method is just a method that belongs to a singleton class. > OK, but my reading of singletons was always as follows. When a singleton > is created, it gets its own singleton class that is a subclass of the > original class. The added method goes in the singleton class. If I define > c.x, it is put in the singleton class, and super is a call to the method > in its superclass, in this case Classic. Defining another c.x just > redefines the method in the singleton class, and super still calls > Classic#x. This would be consistent with explicitly creating the singleton > class, say Classic_c, and redefining Classic_c#x. In this interpretation, > Matz's optimization is completely valid. But it could also be that I > interpreted it that way because that's consistent with the optimization... Yes, that *is* the optimization. You can see it clearly in the sourse code. It checks to see if the object is already pointing to a singleton or not, if it is it reuses the same class. I changed it to check to see if the method is already in the singleton class, if so it makes a "singleton for the singleton" (further subclass). So we still have the optimiztion, just not when the method's previously defined. -t0