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.
A5ae84b6af0a67cdea1db87706a11a6f?d=identicon&s=25 Yoann Guillot (Guest)
on 2006-04-19 03: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
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-04-19 03:52
(Received via mailing list)
Hi --

On Wed, 19 Apr 2006, Yoann Guillot 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 (dblack@wobblini.net)
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!
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-04-19 04:13
(Received via mailing list)
On Apr 18, 2006, at 9:44 PM, Yoann Guillot 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
12271b6df73fe29930d65586be5a4a70?d=identicon&s=25 Dave Howell (Guest)
on 2006-04-19 07:23
(Received via mailing list)
On Apr 18, 2006, at 18:50, dblack@wobblini.net wrote:

> Hi --
>
> On Wed, 19 Apr 2006, Yoann Guillot 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
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-04-19 12:04
(Received via mailing list)
2006/4/19, Yoann Guillot <john-rubytalk@ofjj.net>:
>
> 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
93d566cc26b230c553c197c4cd8ac6e4?d=identicon&s=25 Pit Capitain (Guest)
on 2006-04-19 18:51
(Received via mailing list)
Yoann Guillot schrieb:
>     # self.bar # doesn't work
>     Foo.bar    # need to know the module name

       Module.nesting[ 1 ].bar

>   end
> end

Regards,
Pit
A5ae84b6af0a67cdea1db87706a11a6f?d=identicon&s=25 Yoann Guillot (Guest)
on 2006-04-19 19:13
(Received via mailing list)
Pit Capitain 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 Klemme'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.