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

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 ?

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

···

On Wed, 19 Apr 2006, Yoann Guillot wrote:

--
David A. Black (dblack@wobblini.net)
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!

class Baz
     FooMod = Foo
     ...
     FooMod.bar
end

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

···

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

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.

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

···

2006/4/19, Yoann Guillot <john-rubytalk@ofjj.net>:

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 ?

--
Have a look: Robert K. | Flickr

Yoann Guillot schrieb:

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

       Module.nesting[ 1 ].bar

  end
end

Regards,
Pit

Hi --

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

···

On Apr 18, 2006, at 18:50, dblack@wobblini.net wrote:

On Wed, 19 Apr 2006, Yoann Guillot wrote:

Pit Capitain wrote:

>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

      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 Klemme'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