[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

super's not so super today

Trans

7/18/2006 6:19:00 PM

Can anyone help me get around this?

class C
def r ; "r" ; end
end

module M
def r
#return '{' + super + '}'
target = lambda{ super }
b( target )
end
def b( target )
'{' + target.call + '}'
end
end

module N
def r
target = lambda{ super }
b( target )
end
def b( target )
'[' + target.call + ']'
end
end

class D < C
include M
include N
end

d = D.new
p d.r #=> "[[r]]"

The result should be "[{r}]". Notice the remarked line I left in there,
if you unremark that line it works fine. So what going on? What can I
do to fix this?

Thanks,
T.


9 Answers

Jacob Fugal

7/18/2006 6:36:00 PM

0

On 7/18/06, transfire@gmail.com <transfire@gmail.com> wrote:
> class C
> def r ; "r" ; end
> end
>
> module M
> def r
> #return '{' + super + '}'
> target = lambda{ super }
> b( target )
> end
> def b( target )
> '{' + target.call + '}'
> end
> end
>
> module N
> def r
> target = lambda{ super }
> b( target )
> end
> def b( target )
> '[' + target.call + ']'
> end
> end
>
> class D < C
> include M
> include N
> end
>
> d = D.new
> p d.r #=> "[[r]]"
>
> The result should be "[{r}]". Notice the remarked line I left in there,
> if you unremark that line it works fine. So what going on? What can I
> do to fix this?

Looking at this, I don't think there's anything wrong with you're
super at all, but rather, which b is being called. M#b and N#b collide
when they're both included and you're losing your M#b altogether. If
you rename so that those methods are different, you can see it
working:

$ cat test.rb
class C
def r ; "r" ; end
end

module M
def r
#return '{' + super + '}'
target = lambda{ super }
b( target )
end
def b( target )
'{' + target.call + '}'
end
end

module N
def r
target = lambda{ super }
q( target ) # note the changed method name here
end
def q( target ) # and here
'[' + target.call + ']'
end
end

class D < C
include M
include N
end

d = D.new
p d.r #=> "[{r}]"

$ ruby test.rb
"[{r}]"

Jacob Fugal

Trans

7/18/2006 6:45:00 PM

0


Jacob Fugal wrote:
> On 7/18/06, transfire@gmail.com <transfire@gmail.com> wrote:
> > class C
> > def r ; "r" ; end
> > end
> >
> > module M
> > def r
> > #return '{' + super + '}'
> > target = lambda{ super }
> > b( target )
> > end
> > def b( target )
> > '{' + target.call + '}'
> > end
> > end
> >
> > module N
> > def r
> > target = lambda{ super }
> > b( target )
> > end
> > def b( target )
> > '[' + target.call + ']'
> > end
> > end
> >
> > class D < C
> > include M
> > include N
> > end
> >
> > d = D.new
> > p d.r #=> "[[r]]"
> >
> > The result should be "[{r}]". Notice the remarked line I left in there,
> > if you unremark that line it works fine. So what going on? What can I
> > do to fix this?
>
> Looking at this, I don't think there's anything wrong with you're
> super at all, but rather, which b is being called. M#b and N#b collide
> when they're both included and you're losing your M#b altogether. If
> you rename so that those methods are different, you can see it
> working:
>
> $ cat test.rb
> class C
> def r ; "r" ; end
> end
>
> module M
> def r
> #return '{' + super + '}'
> target = lambda{ super }
> b( target )
> end
> def b( target )
> '{' + target.call + '}'
> end
> end
>
> module N
> def r
> target = lambda{ super }
> q( target ) # note the changed method name here
> end
> def q( target ) # and here
> '[' + target.call + ']'
> end
> end
>
> class D < C
> include M
> include N
> end
>
> d = D.new
> p d.r #=> "[{r}]"
>
> $ ruby test.rb
> "[{r}]"
>
> Jacob Fugal

Ah! Of course, Thank you. Unfortuantely NOW I need class local methods!
:(

T.


Trans

7/18/2006 9:06:00 PM

0


transfire@gmail.com wrote:

> Ah! Of course, Thank you. Unfortuantely NOW I need class local methods!
> :(

Well, this leads me to ask again about these state of affairs for a
future Ruby. Are we going to get local instance vars? I think the
suggested notation was @_. And likewise what of local methods?

If I recall correctly I think that last thing I suggest was making all
instance vars local, which would measn accessors were paramount in
sharing data better levels and then local methods could be defined with


def @method()

But maybe that's too much. Anyway it's just a thought. I don't really
care so much how it's done just so long as it becomes possible. If you
want a usecase, my particular case is defining cross-concerns, I want
to be able to access the internal state of the class hierachy in
general as we do now, while maintiang a separate local state (for the
concern) as well.

On a side note I think I found a bug in Ruby, maybe

class X
def self.method_added(name)
p name
end
end

class X
def x; end
end
=> :x

class << X
undef_method :method_added
end

class X
def y; end
end
=> NoMethodError: undefined method `method_added' for X:Class


</Trans>

Adam Shelly

7/18/2006 9:31:00 PM

0

On 7/18/06, Trans <transfire@gmail.com> wrote:
> On a side note I think I found a bug in Ruby, maybe
>
> class << X
> undef_method :method_added
> end
>
> class X
> def y; end
> end
> => NoMethodError: undefined method `method_added' for X:Class
>
>
You get the same error even if you don't override method_added first.
It looks like the call to method_added is hard-coded in
rb_add_method() in eval.c.. (also in rb_alias())

It seems like a bug to me - the c code should check that callback
methods still exist before calling them.

-Adam

Trans

7/18/2006 9:37:00 PM

0


Adam Shelly wrote:
> On 7/18/06, Trans <transfire@gmail.com> wrote:
> > On a side note I think I found a bug in Ruby, maybe
> >
> > class << X
> > undef_method :method_added
> > end
> >
> > class X
> > def y; end
> > end
> > => NoMethodError: undefined method `method_added' for X:Class
> >
> >
> You get the same error even if you don't override method_added first.
> It looks like the call to method_added is hard-coded in
> rb_add_method() in eval.c.. (also in rb_alias())
>
> It seems like a bug to me - the c code should check that callback
> methods still exist before calling them.

I see. Okay, at least that makes sense. I agree though, I seem more
logical that it would check for the method, rather then hard coding an
empty one into core. But maybe it's more efficient that way?

Thanks,
T.

Sean O'Halpin

7/19/2006 1:06:00 AM

0

On 7/18/06, Trans <transfire@gmail.com> wrote:
>
> On a side note I think I found a bug in Ruby, maybe
>
> class X
> def self.method_added(name)
> p name
> end
> end
>
> class X
> def x; end
> end
> => :x
>
> class << X
> undef_method :method_added
> end
>
> class X
> def y; end
> end
> => NoMethodError: undefined method `method_added' for X:Class
>
>
> </Trans>
>
>
Is it a bug? You are undef'ing it after all. remove_method would seem
more appropriate in this use case.

But maybe a warning like "undefining `method_added' may cause serious
problem" like for __send__, __id__, etc. might be in order.

Regards,
Sean

Sean O'Halpin

7/19/2006 1:46:00 AM

0

On 7/18/06, Trans <transfire@gmail.com> wrote:
>
> transfire@gmail.com wrote:
>
> > Ah! Of course, Thank you. Unfortuantely NOW I need class local methods!
> > :(
>
> Well, this leads me to ask again about these state of affairs for a
> future Ruby. Are we going to get local instance vars? I think the
> suggested notation was @_. And likewise what of local methods?
>
> If I recall correctly I think that last thing I suggest was making all
> instance vars local, which would measn accessors were paramount in
> sharing data better levels and then local methods could be defined with
>
>
> def @method()
>
> But maybe that's too much.

If we ever get local methods, this seems like a reasonable notation to me.

Regards,
Sean

Trans

7/19/2006 1:47:00 AM

0


Sean O'Halpin wrote:
> On 7/18/06, Trans <transfire@gmail.com> wrote:
> >
> > On a side note I think I found a bug in Ruby, maybe
> >
> > class X
> > def self.method_added(name)
> > p name
> > end
> > end
> >
> > class X
> > def x; end
> > end
> > => :x
> >
> > class << X
> > undef_method :method_added
> > end
> >
> > class X
> > def y; end
> > end
> > => NoMethodError: undefined method `method_added' for X:Class
> >
> >
> > </Trans>
> >
> >
> Is it a bug? You are undef'ing it after all. remove_method would seem
> more appropriate in this use case.
>
> But maybe a warning like "undefining `method_added' may cause serious
> problem" like for __send__, __id__, etc. might be in order.

Weel, yea sort of. B/c look at what happended to me. I defined my own
method_added in a paritcular class, and in order to prevent an infinite
loop I need to undefine it in a subclass of it. I.e.

class X
def method_added
... this might define a method in a Y
end
end

class Y < X
remove_method :method_added # goes right back to infinite loop
undef_method :method_added # bombs per our "bug"
def method_added; end # what I ended up with
end

So there's an easy fix but it's seems a bit wasteful. One wuould expect
undef to work and save a call to a noop. Butmaybe it's more efficeint
to just make the call to the noop then it is to see if it's present? I
somehow doubt it though. In whihc case I say it's a minor bug.

T.


Sean O'Halpin

7/19/2006 2:56:00 AM

0

On 7/19/06, transfire@gmail.com <transfire@gmail.com> wrote:
>
> Sean O'Halpin wrote:
> > On 7/18/06, Trans <transfire@gmail.com> wrote:
> > >
> > > On a side note I think I found a bug in Ruby, maybe
> > >
> > > class X
> > > def self.method_added(name)
> > > p name
> > > end
> > > end
> > >
> > > class X
> > > def x; end
> > > end
> > > => :x
> > >
> > > class << X
> > > undef_method :method_added
> > > end
> > >
> > > class X
> > > def y; end
> > > end
> > > => NoMethodError: undefined method `method_added' for X:Class
> > >
> > >
> > > </Trans>
> > >
> > >
> > Is it a bug? You are undef'ing it after all. remove_method would seem
> > more appropriate in this use case.
> >
> > But maybe a warning like "undefining `method_added' may cause serious
> > problem" like for __send__, __id__, etc. might be in order.
>
> Weel, yea sort of. B/c look at what happended to me. I defined my own
> method_added in a paritcular class, and in order to prevent an infinite
> loop I need to undefine it in a subclass of it. I.e.
>
> class X
> def method_added
> ... this might define a method in a Y
> end
> end
>
> class Y < X
> remove_method :method_added # goes right back to infinite loop
> undef_method :method_added # bombs per our "bug"
> def method_added; end # what I ended up with
> end
>
> So there's an easy fix but it's seems a bit wasteful. One wuould expect
> undef to work and save a call to a noop. Butmaybe it's more efficeint
> to just make the call to the noop then it is to see if it's present? I
> somehow doubt it though. In whihc case I say it's a minor bug.
>
> T.
>
Having thought about it a bit more, I'm inclined to agree. There's no
(logical) reason why method_added should be called if you don't define
it yourself, so it seems reasonable to be able to undef it completely
from a class without side-effects.

Regards,
Sean