From: "David A. Black" Date: 2005-09-11T22:39:11+09:00 Subject: Re: confused by nested functions 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