Nested scopes

Hi,

I just discovered a behavior of ruby that seems strange to me.
I have a module containing classes, and i’d like those classes to be
able to call some method of the module, so i tried different solutions :

module Foo
def self.bar
puts “bar!”
end

bar # works

class Baz
# bar # doesn’t work
# self.bar # doesn’t work
Foo.bar # need to know the module name
end
end

I’d like to be able to call the method from Foo::Baz without knowing the
name of the module, but the only way i found is to call Foo.bar from
inside Baz.

Now if you replace “module Foo end” by “Module.new.module_eval {}”…

Shouldn’t ruby walk the nesting stack when it doesn’t find a method name
?
Is this going to change in 2.0 ?

Cheers,
Yoann

Hi –

On Wed, 19 Apr 2006, Yoann G. wrote:

name of the module, but the only way i found is to call Foo.bar from
inside Baz.

Now if you replace “module Foo end” by “Module.new.module_eval {}”…

Shouldn’t ruby walk the nesting stack when it doesn’t find a method name ?

No; it should walk the method lookup path. Inside Baz, self is Baz,
and there’s no bar method defined in Baz’s class (which is Class), nor
in Baz’s singleton class, nor in any module mixed into either of
those. So Baz does not respond to “bar”.

Is this going to change in 2.0 ?

I don’t think it would make sense. Method-calling is determined by
the method lookup path of the receiver.

David


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” PDF now on sale! Ruby for Rails
Paper version coming in early May!

On Apr 18, 2006, at 9:44 PM, Yoann G. wrote:

Foo.bar    # need to know the module name

end
end

I’d like to be able to call the method from Foo::Baz without
knowing the
name of the module, but the only way i found is to call Foo.bar from
inside Baz.
class Baz
FooMod = Foo

FooMod.bar
end

Now you only have to change it in one place at least

On Apr 18, 2006, at 18:50, [email protected] wrote:

Hi –

On Wed, 19 Apr 2006, Yoann G. wrote:

Hi,

I just discovered a behavior of ruby that seems strange to me.

Me too.

Shouldn’t ruby walk the nesting stack when it doesn’t find a method
name ?

No; it should walk the method lookup path.

Fine. Why doesn’t the method lookup path include the scope of the
progenitor, or provide access to it? Your answer merely begs the
question.

Yoann, I ran into the same rather exasperating behavior. Here’s how I
solved it:

module Foo
def self.bar
puts “bar!”
end

bar # works

class Baz
def initialize(parent)
@parentClass = parent
end

def something
   	# bar      # doesn't work
   	# self.bar # doesn't work
   	Foo.bar    # need to know the module name
	@parentClass.bar # works, doesn't need module name hard-coded.
end

end

my_baz = Baz.new(self)
my_baz.something  # no error

end

2006/4/19, Yoann G. [email protected]:

name of the module, but the only way i found is to call Foo.bar from
inside Baz.

Now if you replace “module Foo end” by “Module.new.module_eval {}”…

Shouldn’t ruby walk the nesting stack when it doesn’t find a method name ?
Is this going to change in 2.0 ?

No. But there’s a simple cure (that we might even suggest to go into
the std lib):

class Module
def outer
name.split(‘::’)[0…-2].inject(::Object){|cl,n| cl.const_get n}
end
end

Now you can do

module Foo
def self.yeah; puts “yeah!” end
class Bar
p outer
outer.yeah
class Baz
p outer
end
end
end
p outer

and get

Foo
yeah!
Foo::Bar
Object

:slight_smile:

Kind regards

robert

Pit C. wrote:

self.bar # doesn’t work

Foo.bar # need to know the module name

  Module.nesting[ 1 ].bar

end
end

Thanks, Module.nesting[-2] is quite close of what i need.
However i does not work in

class Foo::Baz
end

In this case i can use Robert K.'s Module.outer, but this one
doesn’t work with anonymous modules :slight_smile:

In my case i’ll just use this workaround, but i still think that’s odd.

I found something close that behaves like i though it would, it’s
constants:

class Parent
PM = ‘parent’
P = ‘parent’
end

module Mod
PM = ‘module’
M = ‘module’

class Foo < Parent
puts M # => ‘module’
puts P # => ‘parent’
puts PM # => ‘module’
end
end

where there is still the problem of

class Mod::Foo
puts M # NameError: uninitialized constant
end

Why is there a difference in the lookup path for constants Vs methods ?

Yoann

Yoann G. schrieb:

# self.bar # doesn't work
Foo.bar    # need to know the module name
   Module.nesting[ 1 ].bar

end
end

Regards,
Pit