Before, after and around Ruby 1.9

I believe Perl 6 takes a similar approach using the `next` keyword/method/whatever (I don't know how it is implemented).

James Edward Gray II

···

On Sep 6, 2007, at 10:35 AM, Yukihiro Matsumoto wrote:

Hi,

In message "Re: before, after and around Ruby 1.9" > on Thu, 6 Sep 2007 13:12:53 +0900, Morton Goldberg > <m_goldberg@ameritech.net> writes:

>Perhaps to avoid overloading 'super', you might use 'previous' or
>'existing' since we would be calling a previously existing version of
>the method.

Interesting idea, especially knowing Common Lisp Object System uses
call-next-method instead of super.

shouldn't this work as expected in this case?

Foo = Class.new(Foo) { def foo; super; end} #AROUND

Actually, it already does, but raises a warning :slight_smile:

···

On Fri, 07 Sep 2007 00:57:09 +0900, Trans wrote:

What if you want to reopen _without_ the "around" semantics? Could we
have these two variations:

class Foo < Foo # <-- This is a type error in 1.8
   def foo; super; end # AROUND
end

Almost an anonymous cut.

class Foo
   def foo; super; end # REDEFINE
end

At least that is a conservative extension.

The downside here is it's static syntax --making it harder to work
with in dynamic metacode.

--
goto 10: http://www.goto10.it
blog it: http://riffraff.blogsome.com
blog en: http://www.riffraff.info

AFAIK "inner" in simula is similar to "inner" in Beta, and is some kind of
dual to super.
i.e.

class C
def foo
  print 'hello'
  inner
end
end

class D < C
def foo
  print ' world'
end
end
D.new.foo #=> hello world

···

On Sun, 09 Sep 2007 02:53:13 +0900, Logan Capaldo wrote:

On 9/8/07, Christian Neukirchen <chneukirchen@gmail.com> wrote:

Yukihiro Matsumoto <matz@ruby-lang.org> writes:

> This works as "around". And "before" and "after" can be rewritten
> using "around". Note that this is not a fixed idea at all.

BTW, do you know how Simula uses "inner"?

He might, but I don't and couldn't find it by googling, so I'd love
some elaboration :slight_smile:

--
goto 10: http://www.goto10.it
blog it: http://riffraff.blogsome.com
blog en: http://www.riffraff.info

Rick, I don't see a way to solve this problem. If you add around
methods to an existing method, the order in which you do this is
always important, regardless of the syntax or the implementation,
isn't it?

Regards,
Pit

···

2007/9/8, Rick DeNatale <rick.denatale@gmail.com>:

Just to try to crystalize my own thoughts about this in general. I'm
concerned that because of the dynamic nature of "assembling" the
pieces of a Ruby program, some of these proposals might lead to
indeterminate (or at best mysterious) results because of the
difficulties in figuring out the order of code parsing/execution. (...)

Kind of ugly. I'll stick with my def thanks. I did like some of the
early code examples/ideas that Matz has put into past presentations.

The above would also make recursive calls quite hard. The bigger
question comes with the combination of two smaller problems: arguments
and recursion. How do we want to treat stacked methods are these like
methods in their own modules or are we going to keep different calling
semantics?

Consider an initial class with a simple method:

class Example
  def fib(n)
    if n > 1
      fib(n - 2) + fib(n - 1)
    else
      1
    end
  end
end

Now we reopen the class and add a new fib:

class Example
  def fib(n, prefix = 'Calculating fib of ')
    puts prefix + n.to_s
    super(n)
  end
end

So in this example, calling fib(2) on an instance of Example would
yield a simple:

Calculating fib of 2
Calculating fib of 0
Calculating fib of 1

That works well because we can always call super with correct
arguments BUT the recursion in the first method could possibly cause
problems. The first method only knows about its own argument so it
forces the calculation to default after the first fib call. So fib(2,
'Try ') would give the confusing output of

Try 2
Calculating fib of 0
Calculating fib of 1

Not so great. So how would one reconcile this problem? Would recursive
calls directly call the current method? Would we use something like
Erlang's reloading which differentiates calls that explicitly give a
target (i.e. self in this case) vs ones that make it implicit?

I do think super is an underused feature of Ruby (generally because it
is so easy to alias things in Ruby). I think the idea is wonderful but
there needs to be serious consideration on some of the calling
mechanisms. The above example is contrived. It might be appropriate to
use the same rules as regular non-stacked super methods.

I can't quite tell what feels right in this case but I think being
able to recurse properly should be a top priority.

Brian.

···

On 9/5/07, Rick DeNatale <rick.denatale@gmail.com> wrote:

On 9/5/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

> >Could we have these two variations:
> >
> >class Foo < Foo # <-- This is a type error in 1.8
> > def foo; super; end # AROUND
> >end
> >
> >class Foo
> > def foo; super; end # REDEFINE
> >end
> >
> >At least that is a conservative extension.
>
> Or maybe providing two supers, one for the current behavior, the other
> for the new. I don't whatever name is suitable for new super yet,
> however

Hi Matz,

super for this new usage just doesn't feel right to me.

Isn't this really looking for syntactic sugar for something like:

class Foo #reopen

  alias_method :old_foo, :foo

  def foo
     old_foo #around
  end
end

So as to avoid needing to explicitly alias the method and come up with a name?

Perhaps instead of super in this case something in the vein of old,
or previous.

Alternatively what about instead of def

class Foo
   around foo
        #do something
        foo
       # do something else
  end
end

Which I would see as internally aliasing the existing foo, and
resolving reference to fo in the new methods body to the alias.

Or instead of around, how about wrap, with a corresponding unwrap to
back out the wrapper method?

> Hi,
>
>
> >What if you want to reopen _without_ the "around" semantics?
>
> I thought we need to remove the previous one first.
>
> >Could we have these two variations:
> >
> >class Foo < Foo # <-- This is a type error in 1.8
> > def foo; super; end # AROUND
> >end
> >
> >class Foo
> > def foo; super; end # REDEFINE
> >end
> >
> >At least that is a conservative extension.
>
> Or maybe providing two supers, one for the current behavior, the other
> for the new. I don't whatever name is suitable for new super yet,
> however.

How would you be sure (and why would you want to?) know when a
"previous" exists or not? It rarely make sense to avoid advice.
However, when absolutely needed one can fallback to directed calling
with things like:

  super_at(Object)

Inheritance dependecies, oooouch, danger, hot do not touch!
Mixin dependecies even worse imagine you want to refer to a mixed in
method, maybe it was mixed in by an anonymous module, or the method
was defined at instance level.

After all it feels wrong to have around, before and after built into
the language, this seems to be a job for the metaprogrammers not for
Matz.
I'd prefer having an easy way to do this with metaprogramming and then
put the implementations into the library.

if there were a method object tree rather than a stack and if each
method object just had references to the defining Module/Singleton
Module, would we not be *very* happy?

module A
   def a; 222 end
end
module A
   def a; 132 end
end
class B
   include A
   def a; 110 end
end
class C < B
   def a; 60 end
end

class C
   include Module::new{ def a ; 52 end }
end

c = C.new
ma = c.method :a
ma = ma.unbind
ma.bind(c).call => 52
ma.old.bind(c).call => 60
ma.super.bind(c).call => 110
and most importantly

D= Class::new {
    define_method :a { -3 + ma.bind(self).call - 3 }
}
D.instance_method(:a).old == ma => true

Cheers
Robert

···

On 9/6/07, Trans <transfire@gmail.com> wrote:

On Sep 5, 6:46 pm, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> In message "Re: before, after and around Ruby 1.9" > > on Thu, 6 Sep 2007 10:32:03 +0900, Joel VanderWerf <vj...@path.berkeley.edu> writes:

or

  as(Object).foo

T.

--
I'm an atheist and that's it. I believe there's nothing we can know
except that we should be kind to each other and do what we can for
other people.
-- Katharine Hepburn

> Joel VanderWerf wrote:
>> What if you want to reopen _without_ the "around" semantics? Could
>> we have these two variations:
>> class Foo < Foo # <-- This is a type error in 1.8
>> def foo; super; end # AROUND
>> end
>> class Foo
>> def foo; super; end # REDEFINE
>> end
>
> +1
>
> This is brilliant. It's simple, and it perfectly expresses the idea
> of reopening the class to add functionality on top of the existing
> methods. Instead of subclassing a parent class, Foo subclasses
> itself (sort of like Foo=Class.new(Foo)). Just Brilliant.

:slight_smile: I think I'm probably missing something, but I'm not sure that I'm
keen on this approach though I find the simplicity alluring.

The issue I have is what happens when the class is re-opened more
than once: when lots of methods get wrapped around? As far as I can
see, the order of the openings in the code is important, and I don't
like the feel of that at all. I feel like I ought to be able to
reorder things such as the order of class definition without that
having a semantic effect. In fact, I think I find it confusing
already that if I define the same method more than once for the same
class, then the last definition will be the one that's used.

Yes, I totally agree, this is a real problem. I fear that things will
all get wrapped up around the axle because it depends on the temporal
ordering of execution. How do you control this when different parts
of the overall program are dynamically requiring extensions and
redefinitions? Imagine how this would or wouldn't work in a Rails app
using multiple plugins.

Am I missing something? Does anyone else feel similarly? Is the
consensus that this wouldn't be an issue in practice?

I suppose I'd prefer something that would somewhat break away from
what happens now...

I'd have all of the implementations of a method (within the class) be
called. I'd then have another mechanism for enforcing ordering: a
syntax that lets an implementation insist that it requires another to
be run before it (or after it). Once you've insisted that another
implementation runs before you, then you're able to utilise the
return state of that method you asked to run before you.

On the surface, I'm not sure that any of the proposed solutions are
any better than what we have now with alias_method and explicit
invocation of the replaced method implementation.

The proposals might make it seem more transparent, but in my
experience, transparency isn't always a good thing when it hides
issues that need to be dealt with. I've got some experience with
that, since I take the blame for producing a transparent distributed
implementation of Smalltalk which caused all kinds of headaches
because of such hidden issues.

···

On 9/6/07, Benjohn Barnes <benjohn@fysh.org> wrote:

On 6 Sep 2007, at 06:17, Daniel DeLorme wrote:

Then again, what I'm asking for could easily be done with a library,
so perhaps it's not so important :slight_smile:

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

^^^^^
  C.new

···

On Sat, 08 Sep 2007 20:00:50 +0200, gabriele renzi wrote:

D.new.foo #=> hello world

--
goto 10: http://www.goto10.it
blog it: http://riffraff.blogsome.com
blog en: http://www.riffraff.info

Yes, my concern is that because there's been so much clever use of
dynamic loading of code in Ruby, and particularly in Rails, that such
constructs might lead to bedlam.

And at least I think that it's an argument for not repurposing super
which has a meaning which depends strictly on the class
inheritance/module inclusion chain and not on how that chain happened
to get to a particular state.

···

On 9/10/07, Pit Capitain <pit.capitain@gmail.com> wrote:

2007/9/8, Rick DeNatale <rick.denatale@gmail.com>:
> Just to try to crystalize my own thoughts about this in general. I'm
> concerned that because of the dynamic nature of "assembling" the
> pieces of a Ruby program, some of these proposals might lead to
> indeterminate (or at best mysterious) results because of the
> difficulties in figuring out the order of code parsing/execution. (...)

Rick, I don't see a way to solve this problem. If you add around
methods to an existing method, the order in which you do this is
always important, regardless of the syntax or the implementation,
isn't it?

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Ahh the emotion go the better of me :wink:
D= Class::new(C) {
    define_method :a { -3 + ma.bind(self).call - 3 }
}
D.instance_method(:a).super == ma => true

Sorry for the ugly error

Cheers
Robert

···

--
I'm an atheist and that's it. I believe there's nothing we can know
except that we should be kind to each other and do what we can for
other people.
-- Katharine Hepburn

> > Hi,

> > >What if you want to reopen _without_ the "around" semantics?

> > I thought we need to remove the previous one first.

> > >Could we have these two variations:
> > >
> > >class Foo < Foo # <-- This is a type error in 1.8
> > > def foo; super; end # AROUND
> > >end
> > >
> > >class Foo
> > > def foo; super; end # REDEFINE
> > >end
> > >
> > >At least that is a conservative extension.

> > Or maybe providing two supers, one for the current behavior, the other
> > for the new. I don't whatever name is suitable for new super yet,
> > however.

> How would you be sure (and why would you want to?) know when a
> "previous" exists or not? It rarely make sense to avoid advice.
> However, when absolutely needed one can fallback to directed calling
> with things like:

> super_at(Object)

Inheritance dependecies, oooouch, danger, hot do not touch!

Well, that was kind of my point. As often as this is useful, so is
skipping over around advice.

Mixin dependecies even worse imagine you want to refer to a mixed in
method, maybe it was mixed in by an anonymous module, or the method
was defined at instance level.

After all it feels wrong to have around, before and after built into
the language, this seems to be a job for the metaprogrammers not for
Matz.

Why exactly? Ruby has many meta-programming features built-in. That's
part of it's charm and power.

I'd prefer having an easy way to do this with metaprogramming and then
put the implementations into the library.

There are two problems with that. 1) any implementation one can create
as an add-on is going to have a less intuitive interface, and 2) but
much more importantly, any such implementation is going to be severely
hampered in execution efficiency compared to a native capability.

T.

···

On Sep 6, 11:54 am, "Robert Dober" <robert.do...@gmail.com> wrote:

On 9/6/07, Trans <transf...@gmail.com> wrote:
> On Sep 5, 6:46 pm, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> > In message "Re: before, after and around Ruby 1.9" > > > on Thu, 6 Sep 2007 10:32:03 +0900, Joel VanderWerf <vj...@path.berkeley.edu> writes:

> D.new.foo #=> hello world
  ^^^^^
  C.new

Interesting, but what if C has more than one subclass?

···

On 9/8/07, gabriele renzi <rff_rffREMOVE@yahoo.it> wrote:

On Sat, 08 Sep 2007 20:00:50 +0200, gabriele renzi wrote:

--
goto 10: http://www.goto10.it
blog it: http://riffraff.blogsome.com
blog en: http://www.riffraff.info

Yes, my concern is that because there's been so much clever use of
dynamic loading of code in Ruby, and particularly in Rails, that such
constructs might lead to bedlam.

This is a valid concern. Integrating AOP in the language can be seen
as one more way to shoot you in the foot. But many of us (I'm sure you
too) like Ruby for the possibilities it gives to the developer, and I
would be very happy to get a standard and efficient AOP
implementation.

And at least I think that it's an argument for not repurposing super
which has a meaning which depends strictly on the class
inheritance/module inclusion chain and not on how that chain happened
to get to a particular state.

The module inclusion chain is already dependent on the sequence in
which the code is executed, especially if you use super. What I like
about Matz's proposal is that there is still only one of these chains
and one way to walk them: super. Having a different way to call the
next method would make things more complicated, IMO. Anyway, I'm
looking forward to 2.0.

Regards,
Pit

···

2007/9/11, Rick DeNatale <rick.denatale@gmail.com>:

>
>
>
> > > Hi,
>
>
> > > >What if you want to reopen _without_ the "around" semantics?
>
> > > I thought we need to remove the previous one first.
>
> > > >Could we have these two variations:
> > > >
> > > >class Foo < Foo # <-- This is a type error in 1.8
> > > > def foo; super; end # AROUND
> > > >end
> > > >
> > > >class Foo
> > > > def foo; super; end # REDEFINE
> > > >end
> > > >
> > > >At least that is a conservative extension.
>
> > > Or maybe providing two supers, one for the current behavior, the other
> > > for the new. I don't whatever name is suitable for new super yet,
> > > however.
>
> > How would you be sure (and why would you want to?) know when a
> > "previous" exists or not? It rarely make sense to avoid advice.
> > However, when absolutely needed one can fallback to directed calling
> > with things like:
>
> > super_at(Object)
>
> Inheritance dependecies, oooouch, danger, hot do not touch!

Well, that was kind of my point. As often as this is useful, so is
skipping over around advice.

Maybe I read you wrong, there should be a way for metaprogrammers to
know where a method was defined, but that should not be the *only* way
to access to super or redefined methods.
Actually
   super_at(object/module/class)
might be a useful tool, but I would like to have
    super
and
    old (or next or whateverMatzLikes :wink:
to just step up one level for "non meta use"

> Mixin dependecies even worse imagine you want to refer to a mixed in
> method, maybe it was mixed in by an anonymous module, or the method
> was defined at instance level.
>
> After all it feels wrong to have around, before and after built into
> the language, this seems to be a job for the metaprogrammers not for
> Matz.

Why exactly? Ruby has many meta-programming features built-in. That's
part of it's charm and power.

Hmm yes sure, but when Matz answered your question about after/before/around
it seemed to me that it would be a special case built in instead a more general.
I might be completely wrong of course :wink:

> I'd prefer having an easy way to do this with metaprogramming and then
> put the implementations into the library.

There are two problems with that. 1) any implementation one can create
as an add-on is going to have a less intuitive interface,

true but it would still be an interface decided upon early

and 2) but
much more importantly, any such implementation is going to be severely
hampered in execution efficiency compared to a native capability.

Losing you here, do you mean that special bytecode would be emitted
for these three constructs that would be more efficent than for method
redefinition?
Interesting topic but I am too ignorant of it :frowning:
Cheers
Robert

···

On 9/6/07, Trans <transfire@gmail.com> wrote:

On Sep 6, 11:54 am, "Robert Dober" <robert.do...@gmail.com> wrote:
> On 9/6/07, Trans <transf...@gmail.com> wrote:
> > On Sep 5, 6:46 pm, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> > > In message "Re: before, after and around Ruby 1.9" > > > > on Thu, 6 Sep 2007 10:32:03 +0900, Joel VanderWerf <vj...@path.berkeley.edu> writes:

--
I'm an atheist and that's it. I believe there's nothing we can know
except that we should be kind to each other and do what we can for
other people.
-- Katharine Hepburn

Here's the sequence dependency I'm concerned about.

class A
  def m
     puts "Hi from A"
  end
end

class B < A
  def m
     puts "And now a wird from my superclass.!"
    super
  end

class B < A
  #fix the typo
  def m
     puts "And now a word from my superclass!"
  end
end

B.new.m

With the current semantics, this will produce:

And now a word from my superclass!
Hi from A

whereas Matz' proposal would produce:

And now a wird from my superclass!
And now a word from my superclass!
Hi from A

How do you REPLACE a method implementation which invokes super in this
brave new world?

···

On 9/11/07, Pit Capitain <pit.capitain@gmail.com> wrote:

The module inclusion chain is already dependent on the sequence in
which the code is executed, especially if you use super. What I like
about Matz's proposal is that there is still only one of these chains
and one way to walk them: super. Having a different way to call the
next method would make things more complicated, IMO.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

> > > > Hi,

> > > > >What if you want to reopen _without_ the "around" semantics?

> > > > I thought we need to remove the previous one first.

> > > > >Could we have these two variations:
> > > > >
> > > > >class Foo < Foo # <-- This is a type error in 1.8
> > > > > def foo; super; end # AROUND
> > > > >end
> > > > >
> > > > >class Foo
> > > > > def foo; super; end # REDEFINE
> > > > >end
> > > > >
> > > > >At least that is a conservative extension.

> > > > Or maybe providing two supers, one for the current behavior, the other
> > > > for the new. I don't whatever name is suitable for new super yet,
> > > > however.

> > > How would you be sure (and why would you want to?) know when a
> > > "previous" exists or not? It rarely make sense to avoid advice.
> > > However, when absolutely needed one can fallback to directed calling
> > > with things like:

> > > super_at(Object)

> > Inheritance dependecies, oooouch, danger, hot do not touch!

> Well, that was kind of my point. As often as this is useful, so is
> skipping over around advice.

Maybe I read you wrong, there should be a way for metaprogrammers to
know where a method was defined, but that should not be the *only* way
to access to super or redefined methods.
Actually
   super_at(object/module/class)
might be a useful tool, but I would like to have
    super
and
    old (or next or whateverMatzLikes :wink:
to just step up one level for "non meta use"

Yes, that's a common consideration, but there's a subtle reason why
you don't really want that, which is what I'm trying to get across.

When someone writes an around advice, they expect it be wrap the the
method being advised. If the programmer of the original method used
#super rather than #old, it wouldn't work. And that's bad. Because the
point is, I should be able to advise any method I want.

Of course, there may arise special cases where skipping advice in
needed, but that is a rare/dangerous meta-coding need, in which case
#super_at should be more than enough to satisfy the requirement, eg.
super_at(self.class) for instance.

> much more importantly, any such implementation is going to be severely
> hampered in execution efficiency compared to a native capability.

Losing you here, do you mean that special bytecode would be emitted
for these three constructs that would be more efficent than for method
redefinition?

No no. I simply mean that any lib built-on top of Ruby's current meta-
programming constructs is going to be much slower (and less robust)
than something built-in to Ruby itself, basically because method
composition operates at such a low-level.

T.

···

On Sep 7, 1:30 am, "Robert Dober" <robert.do...@gmail.com> wrote:

On 9/6/07, Trans <transf...@gmail.com> wrote:
> On Sep 6, 11:54 am, "Robert Dober" <robert.do...@gmail.com> wrote:
> > On 9/6/07, Trans <transf...@gmail.com> wrote:
> > > On Sep 5, 6:46 pm, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> > > > In message "Re: before, after and around Ruby 1.9" > > > > > on Thu, 6 Sep 2007 10:32:03 +0900, Joel VanderWerf <vj...@path.berkeley.edu> writes:

Rick DeNatale wrote:

The module inclusion chain is already dependent on the sequence in
which the code is executed, especially if you use super. What I like
about Matz's proposal is that there is still only one of these chains
and one way to walk them: super. Having a different way to call the
next method would make things more complicated, IMO.

Here's the sequence dependency I'm concerned about.

class A
  def m
     puts "Hi from A"
  end
end

class B < A
  def m
     puts "And now a wird from my superclass.!"
    super
  end

class B < A
  #fix the typo
  def m
     puts "And now a word from my superclass!"
  end
end

B.new.m

With the current semantics, this will produce:

And now a word from my superclass!
Hi from A

Actually it will only produce "And now a word from my superclass!" I assume you just forgot the super in there.

whereas Matz' proposal would produce:

And now a wird from my superclass!
And now a word from my superclass!
Hi from A

My understanding of Matz' proposal is that you would need to specify "class B" to get that result. By specifying "class B < A" you would get the same result as current ruby.

How do you REPLACE a method implementation which invokes super in this
brave new world?

By defining the method in "regular mode" as opposed to "re-open mode"
  regular: class A < Object
  re-open: class A
At the risk of repeating myself I really prefer the previous suggestion:
  regular: class A
  re-open: class A < A

Daniel

···

On 9/11/07, Pit Capitain <pit.capitain@gmail.com> wrote:

A possibility:

class B
   redef m
     puts "And now a word from my superclass!"
     super
   end
end

T.

···

On Sep 11, 7:39 pm, "Rick DeNatale" <rick.denat...@gmail.com> wrote:

On 9/11/07, Pit Capitain <pit.capit...@gmail.com> wrote:

> The module inclusion chain is already dependent on the sequence in
> which the code is executed, especially if you use super. What I like
> about Matz's proposal is that there is still only one of these chains
> and one way to walk them: super. Having a different way to call the
> next method would make things more complicated, IMO.

Here's the sequence dependency I'm concerned about.

class A
  def m
     puts "Hi from A"
  end
end

class B < A
  def m
     puts "And now a wird from my superclass.!"
    super
  end

class B < A
  #fix the typo
  def m
     puts "And now a word from my superclass!"
  end
end

B.new.m

With the current semantics, this will produce:

And now a word from my superclass!
Hi from A

whereas Matz' proposal would produce:

And now a wird from my superclass!
And now a word from my superclass!
Hi from A

How do you REPLACE a method implementation which invokes super in this
brave new world?

Easy:

  class B
    remove_method :m
    def m ... end
  end

Seems to work well with the idea that the method is being removed
making hard to accidentally cover code up.

The main point to make here is that the property of composability is
still a little weird. This makes loading multiple definitions very
fragile since order could easily matter on which things wrap and which
things don't.

Consider the original syntax from Matz's slides (RubyConf '03):

  class Foo
    def foo:pre(*args)
      p 'pre'
    end
    def foo:post(*args)
      p 'post'
    end
    def foo:wrap(*args)
      p 'wrap pre'
      super
      p 'wrap post'
    end
    def foo
      p 'foo'
    end
  end

  Foo.new.foo

Output:
  wrap pre
  pre
  foo
  post
  wrap post

Notice how the pre/post/wrap is syntax defined before and
independently of the foo method. This is a boost to composability
because it waits for foo to exist and if foo is replaced it is still
acting on the correct foo.

This is a big win for dynamic software... the kind written using Ruby.
I still like the super call, and with this syntax, it is easy to keep
it clear on how recursive calls will act. If we aren't careful and
these extensions become widespread, I have a feeling that a lot of
code will find itself breaking other code too easily.

The other side effect of this syntax is that is provides an easy way
to extend into other method specialization features without having
uncooperative and short term syntaxes.

Brian.

···

On 9/11/07, Rick DeNatale <rick.denatale@gmail.com> wrote:

On 9/11/07, Pit Capitain <pit.capitain@gmail.com> wrote:

> The module inclusion chain is already dependent on the sequence in
> which the code is executed, especially if you use super. What I like
> about Matz's proposal is that there is still only one of these chains
> and one way to walk them: super. Having a different way to call the
> next method would make things more complicated, IMO.

Here's the sequence dependency I'm concerned about.

class A
  def m
     puts "Hi from A"
  end
end

class B < A
  def m
     puts "And now a wird from my superclass.!"
    super
  end

class B < A
  #fix the typo
  def m
     puts "And now a word from my superclass!"
  end
end

B.new.m

With the current semantics, this will produce:

And now a word from my superclass!
Hi from A

whereas Matz' proposal would produce:

And now a wird from my superclass!
And now a word from my superclass!
Hi from A

How do you REPLACE a method implementation which invokes super in this
brave new world?

> > much more importantly, any such implementation is going to be severely
> > hampered in execution efficiency compared to a native capability.
>
> Losing you here, do you mean that special bytecode would be emitted
> for these three constructs that would be more efficent than for method
> redefinition?

No no. I simply mean that any lib built-on top of Ruby's current meta-
programming constructs is going to be much slower (and less robust)
than something built-in to Ruby itself, basically because method
composition operates at such a low-level.

Hmm maybe yes, the VM could simply recompile the method, OTOH if Ruby2
will give us the ability we could recompile the method ourselves as we
could e.g. in Squeak.

Cheers
Robert

···

On 9/7/07, Trans <transfire@gmail.com> wrote:

T.

--
I'm an atheist and that's it. I believe there's nothing we can know
except that we should be kind to each other and do what we can for
other people.
-- Katharine Hepburn