From: Alan Stern Date: 2001-10-06T06:02:05+09:00 Subject: [ruby-talk:22140] Variables, constants, and scopes in Ruby I'm having a lot of trouble understanding how scopes and variable storage work in Ruby. The section on Scopes of Constants and Variables in "Programming Ruby" is not explicit enough to help. For example, it says: "Constants may not be defined in methods." Does this mean that the definition can not be statically within a method, or dynamically within a method? This question, at least, can be answered by a simple test: $ ruby class A def m C = 1 -:3: dynamic constant assignment C = 1 ^ Clearly static inclusion is bad. $ ruby class B def m(x) eval x end end obj = B.new obj.m("C = 2") p B::C This produces 2 as output. So dynamic inclusion is okay. But there's no way to tell this just by reading the book. As I understand it, scopes are implemented by the Ruby interpreter by creating name tables, and pushing and popping them onto some stack as it runs. Names are recognized and associated with objects by means of these tables. But this vague explanation leaves a lot unsaid. There must be separate name tables for local variables, instance variables, class variables, and constants. (As an example, each object must contain a table of its own instance variables. And I assume each class object must contain a table of its class variables -- is that so?) At what times are these tables created? Where are they stored? When do they get pushed/popped on the name-lookup stack? Is there more than one such stack for the various types of names? What tables are associated with the top level (outside of all method definitions)? How does loading a file wrapped in an anonymous module protect the caller's namespace? What are the rules for how far to search the stack for a name? Method invocation creates new stack frames that do not get searched for local variables: $ ruby def m i = 1 n p i end def n i = 2 end m prints out 1, not 2. But when a block is executed, the stack frame that was active when the block was created does get searched for local variables: $ ruby i = 1 def m yield end m { i = 2 } p i prints out 2. What are the corresponding rules for constants? How do meta-classes interact with these name-searching rules? A class method is actually stored as an instance method of the class's meta-class. (I know that sounds remarkably cryptic. It means that the code class A def A.m end end actually results in the creation of an anonymous meta-class, which I will call A', and stores the method m as an instance method in A'.) By analogy, I would expect that class variables should actually be stored as instance variables, either in the class or in the class's meta-class. But apparently this is not so; the following code demonstrates both these points: $ ruby class A def m @v = 0 @@w = 1 end def A.n end end x = A.new x.m print "x instance variables: #{x.instance_variables}\n" print "A instance variables: #{A.instance_variables}\n" print "A class variables: #{A.class_variables}\n" print "A instance methods: #{A.instance_methods(false)}\n" class << A # Get access to the meta-class for A print "A' instance variables: #{self.instance_variables}\n" print "A' class variables: #{self.class_variables}\n" print "A' instance methods: #{self.instance_methods(false)}\n" end This produces as output: x instance variables: @v A instance variables: A class variables: @@w A instance methods: m A' instance variables: A' class variables: @@w A' instance methods: n Apparently there is special treatment for class variables. So where do they get stored? There's probably a lot more questions I could ask along these lines, but this is enough for one message. I would appreciate comments from anybody to help clear up some of these points. Alan Stern