Sorry, about the delay. Been working on sandboxing program compiling/
installing -- quite hard to do well.

On Friday 12 December 2003 04:40 am, Peter wrote:
> I know. In a compiled language, the overhead of searching for the class or
> superclass with the appropriate method is at compile-time, while in Ruby
> you need to do the search at run-time because of its dynamism. I don't
> know how much the Ruby interpreter optimizes or can omtimize. Only it
> seemed to get worse when wraps were done by adding singleton classes, but
> that depends on how popular wraps will be. And whether the 90-10 rule
> applies to wraps as well.

True, true. And I really have no idea. I suppose it really depends on just how 
much of a speed hit occurs as to whether it will require special attention.

> > Clearly I have ;-) But please, no cracks on the spelling. I dispise it.
> > And if I had my way, id prbly typ lk ths.
>
> No cracks, promised. They were just congrats :-)

Well. Thank you. :)

> > 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 my impression was that you wanted those singletons to be
> "implicit", that the singleton classes would make up the implementation
> and wouldn't show up explicitly.

"Duh!" [tom's smacks his forehead] I thought you must have already been aware 
of this, and thus must have meant something more specific, but I did not see 
what it was, so i just assumed perhaps it "clicked" for you or something 
instead. Sorry, I see what you're getting at now.

>   class Test
>     def m1
>       ...
>     end
>     def m2
>       ...
>     end
>   end
>
>   wrapper TestWrap
>     def m1
>       ...
>       super
>       ...
>     end
>     def m2
>       ... # no super
>     end
>   end
>
>   class Test
>     wrap TestWrap
>   end
>
> If we have a situation like this, a wrap is always defined in a wrapper
> class. Redefining a wrap happens in the wrapper class. The wrapper is
> explicitly like a subclass (explicit to the programmer that is), and so we
> really can use the same syntax as we've always done in Ruby. Redefining
> the primary method happens in Test, redefining a wrap happens in TestWrap.
> So to the programmer it is no different from using subclassing, except
> that anyone using Test unknowingly also uses TestWrap. That's what I
> meant. Doesn't that kinda solve the syntax problem? A wrapper could still
> refrain from calling super, but that is its constitutional right (we
> should create a constitution for wraps). 

Think they call that an RCR these days :)

> But everything is explicit (since
> subclassing is explicit, and redefining methods is), and it is consistent
> with current Ruby. That's what I was hoping to tell you.

And "duh!" again [tom's smacks his forehead again] I've actually been holding 
on to my notation tighter then I thought! Indeed I was thinking implict, 
actually I was thinking of both ways, implicit and explict. But in all my 
examples I defaulted to implicit and so never really considered the 
significance of their difference -- implict wraps aren't nearly as useful, 
especailly when defining wraps in a class definable way.

So let me just say this is actually brilliant Peter.

> Oh, and we could give a wrapper (say it gets Wrapper as class, like a
> class has Class as class and a module has Module as class) a callback
> method "wrappee_changed" that is called when the class (or wrapper) that
> is wrapped changes such that it can take the right decision. We can give
> Wrapper a private method set_flush(boolean) that sets default behavior of
> "wrappee_changed", but you can redefine it and choose your own behavior.
> That is possible if the layers are explicitly offered to the programmer.

Nice touch!

> But I get the impression that I had the wrong impression and that you
> already thought of all of this...

No. Not to this extent, anyway. For explict I was thinking more along the 
lines of another keyword like "preclude" (I know, bad use of the word) akin 
to include.

  module MyAspect
    ...
  emd
  class MyClass
    preclude MyAspect
  end

Or having a module split into sections, one that does normal mixin including 
and one that does the singleton mixins, but this is weak.

I think you've hit the ultimate notation! :)

> And to go a bit further, I think with inner wraps (as in the ones that get
> flushed when the primary methods is redefined) the "unknowingly" aspect is
> less useful. There's the primary method, then the inner wraps, and then
> the outer wraps, and I get the feeling that the outermost inner wrap is
> what is seen on the outside, and the outer wraps are invisible. And then
> inner wraps is much like subclassing since the collection of inner wraps
> and primary method really make up the whole of the method.

Well put. That's very much the case. In fact if you think about how wraps are 
approached now, they are down by aliasing. So for example:
 
  alias _meth_ meth
  def meth
    # pre code
    _meth_
    # post code
  end

Obviously this is a bit of hack approach, since to generalize you have to get 
really tricky (as I did with my GUI), but the point is that the interface 
that is then seen is the new method, not the old, as with the outer most 
inner wrap.

In fact, I was thinking about this today, and realized clearly that this is 
the other way in which wraps can implemented. I wonder if Matz is thinking 
along these lines rather then our subclassing line? It's not a far shot to 
imagine that his notation:

  def meth:wrap
    # pre code
    super
    # post code
  end

actually translates under the hood into something like:

  alias_method 'meth:wrap'.intern :meth
  def meth
    # pre code
    send('meth:wrap')
    # post code
  end

which is certainly doable, and probably faster in execution, but nowhere near 
as clean and flexible as our approach. Something to think about though in 
comparision.

> And besides this distinction between inner and outer wraps, there is also
> the kind of wrap that is used for chaining hooks, like method_missing,
> inherited, method_added, ... but that feels like a different kind of
> application of wraps altogether. It feels more method based and making a
> complete layer for it seems overkill.

I agree. That kind of wrapping really needs to be left to the interpretor 
itself to expose.

> I suck at AspectJ lingo too. Java should still be doable. I just used
> AspectJ lingo (or my version of it) because that is existing syntax, in
> Ruby it would be speculative. But I don't really know what you mean with
> the hash. My first idea would be to say that it is like a hash indexed by
> the objects that are linked.
>
> Wait, let me put it this way. Without aspects, a bidirectional link would
> look like this:
>
>   class A
>     def link2B=(objB)
>       @link2B = objB
>       # and other stuff to keep the links consistent
>     end
>   end
>
>   class B
>     def link2A=(objA)
>       @link2A = objA
>       #  and other stuff to keep the links consistent
>     end
>   end
>
> Maintaining those links (i.e., if object1 points to object2, then object2
> should also point to object1) is a cross-cutting concern (it involves data
> in two classes), we would like to make it an aspect. Then the aspect could
> declare @link2B and @link2A to be private to the aspect, such that both
> link2B= and @link2A can access them because they belong to the aspect, but
> other methods in class A and B can't. The only way to move @link2B and
> @link2A to the module containing the aspect methods, would be by
> introducing two hashes @@link2A and @@link2B that respectively map object
> of class B to objects of class B and vice versa.

I've decided I must be totally missing something here, because I'm just not 
fully following. I see that you want instance variables private to an Aspect, 
unseen to the classes the aspect effects, but thats all I can really gather. 
For instance, "and other stuff to keep the links consistent", just dosen't 
mean anything to me. Sorry if I'm being dense, sometimes I can't see what's 
staring me right in the face. I'm going to go back and look at your 
bidirectional example. Maybe that will help it click for me.

Anyway, don't think I'm against this idea or anything, I'm just not yet 
understanding it.

> > 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?
>
> OK. But first I'd want your opinion on what I mentioned above about
> introducing wrappers next to modules and classes. Wrappers would inherit
> from modules just like classes BTW.

umm... "super duper superb". Will that do?

Further, I have some ideas to elaborate on this too, but I'm a too tired to go 
into iit right now. I'll put it in another post.

> PS: I wanted to do something like this today, to provide for the future
> addition of indicators, but it didn't work:
>
>   class Test
>
>     def test
>       instance_methods(true).each do |m, i = ''|
>         if i =~ /silly_indicator/
>           ...
>         end
>       end
>     end
>
>   end
>
> Apparently blocks can't have default values for arguments...

Very foward thinking!

-- 
T.