From: Charles Comstock Date: 2004-04-15T00:49:17+09:00 Subject: Re: Interesting Scoping Rules Dick Davies wrote: > * Charles Comstock [0424 01:24]: > > Take this with a pinch of salt, I am on my first cup of caffeine > - I'm sure I'll get corrected if it's glaringly wrong. (I hope so) > > >>val = "fem" > > > This defines a local variable called 'val' on Object > - not the same as an instance variable. > > >>class Test >> puts val >>end > > > Test can't see the local variable on Object, you get an error like: > > in `t': undefined local variable or method `val' for # (NameError) > from aaa:5 > > So you'd need an accessor on Object to get to it, and even then I think it's gone > out of scope. > (This of course won't print anything until you call Test.new either). > It's not so much that it hasn't gone out of scope here, so much as it is no longer accessable from the inner scope. If I use val further on after the class def it will work perfectly fine. > *this* works: > > class Test > val = "fem" > puts val > end > Test.new > > >># or >> >>class Test >> val = "A" > > >> def info >> puts val >> end >>end >> >>Test.new.info > > > you can't see val here because it's not an instance variable of Test > objects, it's a local variable of the Class Test. Even if you make it an > instance variable, and call it directly then > you have problems, because there is no accessor method defined: > > rasputin@lb:tmp$ cat bbb.rb > class Test > @val = "A" > def info > puts Test.val > end > end > Test.new.info > rasputin@lb:tmp$ ruby -w bbb.rb > bbb.rb:4:in `info': undefined method `val' for Test:Class (NameError) > from bbb.rb:7 > > > >># or >> >>val = 1 >>def t >> puts val >>end >>t > > > I think this is because val is a local variable, not an instance variable of > Object. Again, it's gone out of scope by the time you call t(). > If you replace val with @val, it prints '1', which is what you'd probably expect. > > >>Why is it none of these are allowed? All of these seem like perfectly >>logical places that lexical scoping would allow. It really suprised me >>that none of thse work, anyone have an explanation for this behavior? > > I guess I should have qualified my statement a little better, I did recognize that a def seems to be a hard scoping boundary, the question was much more that I was very suprised by this, and was curious if anyone had any insight as to WHY ruby chose to work things like this? It suprises me much in the same way that we cannot def inside a def, it will result in a new def at the top scope. It also suprises me in the way that if we stick a class inside of a class instance variables will not bubble down into the inner class. Was this all just a sorta clever way to avoid needing to back check up all scopes each time a variable is used? It just goes against my general programming language intuition, it feels singularly un-schemeish in a place I expected it to act scheme-ish, let alone java-ish, c++ish and most other programming languages I can think of. I'm sure I'll get over it as it does most other things the way I like, but it quite suprised me. Charles Comstock