From: Brian Mitchell Date: 2007-09-06T13:15:15+09:00 Subject: Re: before, after and around Ruby 1.9 On 9/5/07, Rick DeNatale wrote: > On 9/5/07, Yukihiro Matsumoto 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? > 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.