super's not so super today

T

transfire

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.
 
J

Jacob Fugal

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
 
T

transfire

Jacob said:
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.
 
T

Trans

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>
 
A

Adam Shelly

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
 
T

Trans

Adam said:
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.
 
S

Sean O'Halpin

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
 
S

Sean O'Halpin

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
 
T

transfire

Sean said:
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.
 
S

Sean O'Halpin

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top