From: "David A. Black" Date: 2009-10-01T23:47:40+09:00 Subject: [ruby-core:25887] Re: struggling to convince myself 1.9's constant lookup rules make any sense This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. --1926193751-1627104459-1254408445=:14116 Content-Type: TEXT/PLAIN; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8BIT Hi -- On Wed, 30 Sep 2009, The Flandrian wrote: > > >> >> in the above code changing from a constant to a variable - or fully >> scoping the contant - are both obvious fixes. �however i don't >> understand how this new behavior isn't at odds with the fundamental >> concept of 'closure': can a closure which only encloses *some* of it's >> state really be called a closure? >> > > > one clarification on that - it makes enough sense that the constant > lookup would start in the receiver, but why would it *stop* there? > aka, if not found in the scope in which the block was called why > wouldn't the lookup continue in the scope of the closure? First thought: because the purpose of the rule, I think, is to clarify that there's a distinction, and the cost of that clarification is that it's a mistake not to make the distinction. For example: class C def self.run(&block) class_eval(&block) end end class D MyConst = 1 C.run { p MyConst } end That code will give you "unknown constant C::MyConst" in 1.9. The reasoning, as I understand it, is that the caller cannot depend one way or the other on whether there's a constant called MyConst in the evaluating class. In other words, there could be: class C MyConst = 2 etc., in which case the call from D would not use D::MyConst -- so since D has no jurisdiction over whether C::MyConst exists, the only consistent approach is to assume that C will *always* have the responsibility for resolving MyConst. It reminds me (maybe not one-to-one, but generally) of the instance_eval thing with instance variables: class E def x(&block) @x = 1 instance_eval(&block) end end @x = 2 p E.new.x { @x } # 1 Here, since instance variables are always resolved via self, the @x in the block is always the @x of the E instance. (I'm not a big fan of the stealth instance_eval, for what it's worth.) I think something analogous is (now) going on with constants. (I do not mean that self is the same as an enclosing class, nor that instance variables are the same as constants, nor anything else that I didn't say unless it's very insightful and brilliant :-) I'm not sure about how this plays out with regard to the technical definition of a closure. I've always taken it to mean the local variable bindings, and not necessarily the rest of the runtime state. David -- David A. Black, Director Ruby Power and Light, LLC (http://www.rubypal.com) Ruby/Rails training, consulting, mentoring, code review Book: The Well-Grounded Rubyist (http://www.manning.com/black2) --1926193751-1627104459-1254408445=:14116--