On Sun, May 27, 2007 at 06:25:09AM +0900, Henrik Schmidt wrote:
> >(1) All objects are descendants of Object, which in turn mixes in Kernel.
> >Many other objects mix in Enumerable, Comparable and other modules.
> >
> >This means that a typical object has roughly a googol different methods
> >already present, and it's very easy to pick a local variable name which
> >happens to collide with one. Silently ignoring this "just works". Giving an
> >error would be very annoying; instead of "id = 9" I'd have to change it to
> >"my_id = 9" or somesuch. In the end I'd prefix all local variables with
> >my_... which would be worse than using something perlish like "$"
> 
> Hmmm, I didn't think of that. Local variable/method ambiguity is only a 
> problem within the class. If you mix in something, you need to be aware 
> of which methods these mixins have. Otherwise you, or anyone who uses 
> your class might get unexpected results. If I decide to give all my 
> classes an id method, someone calling the my_class.id will probably not 
> get the result he wanted.

I disagree. If someone uses your class, then he or she will look at your
rdoc documentation, and see you have an 'id' method and, if it's what they
want to use, will call it.

Now of course, this hides the system 'id' method (which happens to be
deprecated anyway). But you'll find this done where it's appropriate, e.g.
ActiveRecord uses foo.type = bar

However, this has no impact at all on local variables. If a user of your
class decides to write "id = 123", then this *always* generates a local
variable, and this can be seen immediately, by inspection of the code
locally, without having to cross-reference to the class definition.

Equally, if you do

  class Myclass < Other
    def foo
      ...
      x = 1
      ...
    end
  end

then you don't have to worry whether class Other has a method called 'x' or
not (or if it doesn't today, that perhaps it might grow one tomorrow). It's
unambiguously a local variable called 'x' that you're using.

> class Point
>    attr_accessor :x, :y
> 
>    def initialize(init_x,init_y)
>       x, y = init_x, init_y
>    end
> end
> 
> p Point.new(10,10).x => nil
> 
> That's a fair mistake. The compiler doesn't know about the attr_accessor 
> so it thinks x and y are local variables. What I don't understand is, 
> that even if you put in the appropriate methods instead of relying on 
> attr_accessor, it still doesn't work.

Because of the very simple rule that says "a statement of the form 'x = ...'
*always* makes x a local variable from this point until the end of the
current scope". If you want to call a method called 'x=' then you always
need to do self.x=

I sympathise with your concern - a few times I've written some code which
fails unit tests and had to stare at it for a while, before realising what
I'd done. This is particularly true for ActiveRecord, which has lots of
accessors, and where you might be tempted to write "something = nil" instead
of "self.something = nil"

However, if you want a warning for the code above, I think a better one
would be "local variable x assigned but not used". Actually that shouldn't
be too hard to add, and I imagine it could indeed catch a few silly typos.

Regards,

Brian.