Forum: Ruby Nested scopes

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Yoann G. (Guest)
on 2006-04-19 05:45
(Received via mailing list)
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
unknown (Guest)
on 2006-04-19 05:52
(Received via mailing list)
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 (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" PDF now on sale!  http://www.manning.com/black
Paper version coming in early May!
Logan C. (Guest)
on 2006-04-19 06:13
(Received via mailing list)
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
Dave H. (Guest)
on 2006-04-19 09:23
(Received via mailing list)
On Apr 18, 2006, at 18:50, removed_email_address@domain.invalid 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
Robert K. (Guest)
on 2006-04-19 14:04
(Received via mailing list)
2006/4/19, Yoann G. <removed_email_address@domain.invalid>:
>
> 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

:-)

Kind regards

robert
Pit C. (Guest)
on 2006-04-19 20:51
(Received via mailing list)
Yoann G. schrieb:
>     # self.bar # doesn't work
>     Foo.bar    # need to know the module name

       Module.nesting[ 1 ].bar

>   end
> end

Regards,
Pit
Yoann G. (Guest)
on 2006-04-19 21:13
(Received via mailing list)
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 :)

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
This topic is locked and can not be replied to.