From: Devin Mullins Date: 2005-09-11T16:08:53+09:00 Subject: Re: confused by nested functions 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?) #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. --- So... The best way to do what you actually want depends on what you actually want. Are you just trying to group a bunch of similar methods inside a subcomponent of Test, or do you want the Test.boo.moo method to be dynamically generated based on what Test.boo does? If the latter, then keep in mind that every method call returns an Object. What you want to do is make Test.boo return an Object that has a moo method on it. Devin