Hi --

On Sun, 11 Sep 2005, Devin Mullins wrote:

> Navindra Umanee wrote:
>
>> Why does the first one work but not the second one?
>> 
> As mathew said, def is just a command to define a method, it runs when the 
> interpreter gets to that line. What makes the first one work and the second 
> one not, however, is a matter of scope. When 'def' is called, it defines a 
> method in a certain place. That place is determined by what 'class' or 
> 'module' it's in. So class Test; def foo; end end defines a method on Test 
> objects.
>
> #1: def moo; puts 'moo' end is *not inside a 'class' or 'module' block*. This 
> is important. You may be defining a class method boo on Test (well, a 
> singleton method on the Test object), but your @@class_variables won't 
> actually be class variables of Test, because it's outside the class block. 
> It's out in the wild. Here's what the PickAxe2 (p. 346) has to say about 
> that:
>
> "Outside a class or module definition, a definition with an unadorned method 
> name is added as a private method to class Object, and hence may be called in 
> any context without an explicit receiver."
>
> So what's happening here?
>
> Test.boo calls the Test.boo method you defined, which defines a private 
> method moo on Object. The 'def' keyword, as you've seen returns nil. So 
> Test.boo returns nil. Test.boo.moo tries to invoke the moo method on the nil 
> object. Since nil.is_a? Object, it has the moo method that you just defined.
>
> (I'm thinking the PickAxe may be wrong? about the private thing since you can 
> call #moo with an explicit receiver -- sounds more like public. Can somebody 
> explain?)

I think the private thing depends on lexical scope.  Since the nested
definition of moo is not lexically a top-level definition, it isn't
privatized.

> #2: When Test.boo is called, moo is defined as an instance method on Test. 
> Test.boo returns nil, as before, but nil is not a Test object, so the moo 
> method does not exist.

What I find interesting is this:

   class D
     def D.boo
       def moo
         puts "moo"
       end
     end

     def bee
       def mee
         puts "mee"
       end
     end
   end


   D.boo
   d = D.new
   d.bee

   p D.instance_methods.sort  # includes both moo and mee


Nesting a definition inside a class method, and nesting a definition
inside an instance method, have exactly the same effect: an instance
method is added to the class.  In one case, this means "self"; in the
other, it means "self.class".  I'm not sure why it works this way.
Maybe the real rule is "one lexical layer up", which would take both
to the class-definition scope that surrounds them.


David

-- 
David A. Black
dblack / wobblini.net