Followup question on defining methods dynamically

Simple example that doesn't work:

···

----------------
module Test
p "Testing"
eval("def foo\np 'OK'\nend")
foo
end
----------------

'foo' does not get defined in a place where it can be found by the call on foo, and I get an error. However, when I execute the two lines

eval("def foo\np 'OK'\nend")
foo

in IRB, everything works. I'm guessing that this is a namespace problem, but can't see why it would be. Then again, I'm accustomed to the Python namespace model, and still don't understand all of the ways in which the Ruby model is different.

Thanks for any suggestions,
Ken

Hi --

Simple example that doesn't work:

----------------
module Test
p "Testing"
eval("def foo\np 'OK'\nend")
foo
end
----------------

'foo' does not get defined in a place where it can be found by the call on foo, and I get an error. However, when I execute the two lines

eval("def foo\np 'OK'\nend")
foo

in IRB, everything works. I'm guessing that this is a namespace problem, but can't see why it would be. Then again, I'm accustomed to the Python namespace model, and still don't understand all of the ways in which the Ruby model is different.

Your first example is essentially doing this:

   module Test
     def foo
       p "OK"
     end

     foo
   end

When you define an instance method inside a module, you're defining it
for the future use of objects with that module in their ancestry:

   class C
     include Test
   end

   C.new.foo # OK

David

···

On Sat, 4 Aug 2007, Kenneth McDonald wrote:

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Do modules not execute their own code (such as the 'p "Testing"') below in their own namespace, then? I'm doing something that's not at all object-oriented, and simply want to ensure that a bunch of methods don't leak out into the global namespace. One module will define those methods, and other modules (not classes, unless I really have to hack it that way) will use the first module, eg.

module Test
    p "Testing"
    eval("def foo\np 'OK'\nend")
end

module Run
    include Test
    foo
end

The above doesn't work, for the reasons you gave, but I still don't understand the semantics of why not, I'm afraid. No doubt my Python way of thinking. In Python, the equivalent code would create two modules, Test and Run, which are effectively just hashmaps mapping names to objects. The eval would define a 'foo' object in Test, so there would exist a function Test.foo. The include statement in Run (equivalent to Python's "from Test import *" I believe) would cause all names in Test to be imported into Run, resulting in a 'foo' entry in the Run hashmap; this would be Run.foo. Finally, code run within a module always has access to the module's namespace (hashmap) for variable lookup, so the call on 'foo' within Run would find 'Run.foo' and execute it.

Now, since that interpretation is obviously incorrect in Ruby, could someone provide details as to what is actually going on? If possible, I prefer explanations of the 'behind-the-scenes' stuff--how variables are looked up, namespaces are defined, etc., as understanding the background mechanisms will then make everything else pretty easy.

Thanks,
Ken

dblack@rubypal.com wrote:

···

Hi --

On Sat, 4 Aug 2007, Kenneth McDonald wrote:

Simple example that doesn't work:

----------------
module Test
p "Testing"
eval("def foo\np 'OK'\nend")
foo
end
----------------

'foo' does not get defined in a place where it can be found by the call on foo, and I get an error. However, when I execute the two lines

eval("def foo\np 'OK'\nend")
foo

in IRB, everything works. I'm guessing that this is a namespace problem, but can't see why it would be. Then again, I'm accustomed to the Python namespace model, and still don't understand all of the ways in which the Ruby model is different.

Your first example is essentially doing this:

  module Test
    def foo
      p "OK"
    end

    foo
  end

When you define an instance method inside a module, you're defining it
for the future use of objects with that module in their ancestry:

  class C
    include Test
  end

  C.new.foo # OK

David

Hi -

Do modules not execute their own code (such as the 'p "Testing"') below in their own namespace, then?

They do execute their own code, but the code being executed is an
instance method definition. Like 'p "testing"', the method definition
gets executed when it's encountered. But it still has a particular
effect, namely creating an instance method for objects that use this
module.

I'm doing something that's not at all object-oriented, and simply want to ensure that a bunch of methods don't leak out into the global namespace. One module will define those methods, and other modules (not classes, unless I really have to hack it that way) will use the first module, eg.

module Test
  p "Testing"
  eval("def foo\np 'OK'\nend")
end

module Run
  include Test
  foo
end

The above doesn't work, for the reasons you gave, but I still don't understand the semantics of why not, I'm afraid. No doubt my Python way of thinking.

[...]

Now, since that interpretation is obviously incorrect in Ruby, could someone provide details as to what is actually going on? If possible, I prefer explanations of the 'behind-the-scenes' stuff--how variables are looked up, namespaces are defined, etc., as understanding the background mechanisms will then make everything else pretty easy.

Basically, it works like this: every time you send a message to an
object, the object searches along a lookup path consisting of classes
and modules, looking for a corresponding method. The path includes
the object's class, and also any modules that the class includes, and
modules included by those modules, etc.

Modules are themselves objects. That means that when you send a
message to a module, it looks for that method in its lookup path.
However, a module does not lie in its own lookup path (unless you
include it in itself).

A module (and a class) has a kind of dual identity: it's a repository
of instance methods for other objects, and it's also an object in its
own right. These two roles are fairly strictly delineated. You can't
do this:

   class C
     def x
     end
   end

   C.x

because x is defined for the use of instances of C, not C itself.
Similarly, you can't do this:

   module M
     def x
     end
   end

   M.x

for the same reason. And this:

   module M
     def x
     end

     x
   end

is exactly the same: you're sending the message "x" to the module
object M, but that object doesn't have an x method.

David

···

On Sat, 4 Aug 2007, Kenneth McDonald wrote:

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Hi -

<snip>

Modules are themselves objects. That means that when you send a
message to a module, it looks for that method in its lookup path.
However, a module does not lie in its own lookup path (unless you
include it in itself).

Hmm I think it might be useful to clarify this a little bit
when David talks about including a module in itself he means including
it into the lookup array of itself, this is done with extend, not with
include.
As a matter of fact you cannot do this:
module A
   def a; 110 end
   include self
end
it does not make sense either, right, however you can do this of course
module A
   def a; 132 end
   extend self
   p a
end
a different way to do this is
modue A
   def a; 222 end # that is a nice way to say 42 :wink:
   module_function :a
end
Now a is not available as *public* instance method anymore it becomes *private*.

Cheers
Robert

···

On 8/3/07, dblack@rubypal.com <dblack@rubypal.com> wrote:

On Sat, 4 Aug 2007, Kenneth McDonald wrote:

--
[...] as simple as possible, but no simpler.
-- Attributed to Albert Einstein

Yep, it's the extend that did it for me.

I now have a much better idea of Ruby lookup mechanisms :slight_smile:

Many thanks to both you and David,
Ken

Robert Dober wrote:

···

On 8/3/07, dblack@rubypal.com <dblack@rubypal.com> wrote:
  

Hi -

On Sat, 4 Aug 2007, Kenneth McDonald wrote:

<snip>
  

Modules are themselves objects. That means that when you send a
message to a module, it looks for that method in its lookup path.
However, a module does not lie in its own lookup path (unless you
include it in itself).
    

Hmm I think it might be useful to clarify this a little bit
when David talks about including a module in itself he means including
it into the lookup array of itself, this is done with extend, not with
include.
As a matter of fact you cannot do this:
module A
   def a; 110 end
   include self
end
it does not make sense either, right, however you can do this of course
module A
   def a; 132 end
   extend self
   p a
end
a different way to do this is
modue A
   def a; 222 end # that is a nice way to say 42 :wink:
   module_function :a
end
Now a is not available as *public* instance method anymore it becomes *private*.

Cheers
Robert