From: "T. Onoma" Date: 2003-11-30T21:40:52+09:00 Subject: Re: Underpinnings of Method Wrapping On Sunday 30 November 2003 10:38 am, Mauricio Fern�ndez wrote: > This works fine with singletons, but there is a problem if you want to > do it for "normal" instance methods (i.e. wrapping the method for all > objects of a given class), see [ruby-talk:75334] for an explanation and > [ruby-talk:75290] for an implementation using an explicit indication > "plz make this method available with super after redefinition". Thank you very much for pointing this post out. It contains a very interesting point that requires some close analysis. In doing so we will discover that it is actually a little short sighted, but nonetheless hints at a very interesting direction for extending the capabilites of mixins, that is subequently the basis for class definable singletons. Let me explain. The first thing to notice is that Matz' solution only solves the proposed problem to one degree, i.e. for one layer of wrapping. Beyond that you run into the same issue --if Array had also defined each:before (now each:pre) then the order of occurance would again be the only available criteria for determining the wrap stack order. So even with Matz's solution the problem is not solved for the general case. One could also argue, that the problem itself is a bit dubious, b/c #each is not defined by Enumerabe, but rather defines methods that utilize #each as given by other classes that mixin Enumerable. Moreover, by their very nature Mixins do not prepend, like singletons, but rather append, like superclasses. So the notion is a bit misconceived from the get-go. But I am not one to nitpick such "excuses"! It is understandable that one might think of doing something like this as a convenient way to aspect classes that partake of Enumerability. So... To accomplish this means we must somehow overcome the fact that Mixins only append. Take this working "hack-up": class Array def testing print "T" end end enum = Enumerable.dup enum.module_eval { def each print "before" super end def testing print "(" super print ")" end } a = [1,2] a.extend(enum) a.each { |i| print i }; puts # => before12 a.testing; puts $ => (T) This achieves the desired result becasue we have prepended the Enumerable module to the Array using extend, as opposed to the "under the hood" appending that occurs with 'include Enumerable'. So what would it take to generalize this in a class definable way? It is of course, essentially the same means that is required to generalize singleton definitions in a class defineable way. In the particluar case of Mixins, an interesting possibility comes to mind: module Enumerable prepend # <= keyword def each puts "before" super end # prepend :each # <= maybe an additional way to do it end So everything following the prepend keyword would be prepended as "mixin singleton class" rather then appended as "mixin superclasss". And so are problem is solved in all cases. --- On a side note, it is interesting to consider the fact that we don't have the keyword super for classes and modules. class Array super ... end So that without super we could completely redefine Array, while with super, it would mean we are adding to it, as we currently do. As it stands, I wonder, is there even a way to wholly and easily redefine any built-in class or module? A way does not immediately come to mind, albiet this is something that would be extremely rare anyway. --- It should be apparent enough by now that much of what I'm proposing is greater uniformity in the way methods, classes, and modules are defined and manipulated. There is no doubt in my mind that this would make Ruby a better language. Take a look at the general criteria of a good language as given by Lambda the Ultimate and you will see Uniformity as second on the list under Simplicity. 1. Simplicity 2. Uniformity 3. Orthogonality ... from http://lambda.weblogs.com/criteria -t0