Unexpected scope range

Discussion in 'Ruby' started by Andreas Warberg, Dec 5, 2006.

  1. I am new to Ruby but have a strong java background.

    So far I have been enjoying Ruby a great deal.

    But I have been wondering about why the scope of variables works as it
    does. It seems that very often, I need to prefix my variables with
    either @ or $ in order to access them in method calls.
    I did some searching for an explanation but did not find any.

    In java variables can be defined and used like this:

    Object x = myX;

    public void printx(){
    System.out.println(x);
    }

    x is available when the method is called. This is not the case with
    Ruby:

    x = myX

    def printx
    puts x
    end

    Running the code will produce an error: "NameError: undefined local
    variable or method `x' for main:Object".

    In order to reveal x to the method one must, for instance, declare it
    global by prefixing the $. This requires more typing (which, in many
    other respects, ruby tries to avoid).

    How come the scope works in this way? I expected the visibility of
    variables to flow down into the code tree (but not up, of course).

    Thank you.

    Regards, Andreas
     
    Andreas Warberg, Dec 5, 2006
    #1
    1. Advertisements

  2. Andreas Warberg

    gwtmp01 Guest

    This doesn't seem like standard terminology to me. Usually these
    are simply called 'instance variables' as each instance of a class
    (or each object if you prefer) has its own private set of instance
    variables. These variables belong to the instance (object) and not
    to the associated class.

    Gary Wright
     
    gwtmp01, Dec 5, 2006
    #2
    1. Advertisements

  3. Andreas Warberg

    dblack Guest

    Hi --

    def starts a new local scope, so local variables defined outside it
    won't be visible. I can't answer the question defensively -- that is,
    I can't say why it is in relation to Java, since I have no reason to
    think it was designed in relation to Java :)

    Instance variables (@this) are always associated with, and owned by,
    whatever object is in the role of "self", the default object. Inside
    a method definition, self is (or is going to be, when the method
    eventually gets called) the object running the method.

    Global variables ($this) are just global variables, and have the usual
    properties of such variables: they walk through walls, so to speak,
    when it comes to scope, and generally discourage nice encapsulation of
    code and interaction of objects.


    David

    --
    David A. Black |
    Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
    DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
    [1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
    [2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
     
    dblack, Dec 5, 2006
    #3
  4. Thanks for your replies.

    It would seems this is just something I have "gotten used to" with java.
    Looking over some of the things I did in the past (in learning ruby) it
    is clear that constants (variables with capital starting letter), which
    do flow past def statements could have removed a great part of my $'s.
    To illustrate the difference between local and constant variables:

    x=1
    def print_local
    puts x
    end

    (fails)

    X=1
    def print_constant
    puts X
    end

    (prints value of capital X)

    Best regards
    Andreas
     
    Andreas Warberg, Dec 5, 2006
    #4
  5. Andreas Warberg

    Olivier Guest

    Le mardi 05 d=E9cembre 2006 17:45, Paul Lutus a =E9crit=A0:
    As a Java programmer, you are used to declare any attribute (ie instance=20
    variables) in the "body" of the class, outside any method. This is not how =
    it=20
    works in Ruby, because no declaration is needed. So, as Paul wrote, you can=
    =20
    use directly @example within your methods with nothing more elsewhere.
    If you are a bit confused of not having a place, in a class, where to put =
    all=20
    your instance variables, put it in the initialize method.

    Note that int this class :

    class A
    @var
    def meth
    @var
    end
    end

    the two @var are not the same !

    About global variables, I personnaly never used them. It's useful for thin=
    gs=20
    like $stdin or $DEBUG, but nothing more.

    =2D-
    Olivier
     
    Olivier, Dec 5, 2006
    #5
  6. Andreas Warberg

    Eric Hodel Guest

    There is no such thing as a "class instance variable" in Ruby.
    Classes are real objects too, and they have "instance variables" just
    like everybody else.
     
    Eric Hodel, Dec 6, 2006
    #6
  7. Andreas Warberg

    dblack Guest

    Hi --

    Sometimes people say "class instance variable" to mean "instance
    variable of a class object", if for some reason it seems like just
    saying "instance variable" might sound like it means "instance
    variable in an instance method" (and I think that ambiguity can arise,
    in some conversational contexts). But "class instance variable" never
    means or implies or connotes "instance variable" in general, and at
    the language level there's no separate "class instance variable"
    construct or entity.


    David

    --
    David A. Black |
    Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
    DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
    [1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
    [2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
     
    dblack, Dec 6, 2006
    #7
  8. Andreas Warberg

    dblack Guest

    No, that's wrong. Classes are unambiguously and unequivocally
    instances of the class Class.

    The "classes are objects too" principle is very, very important in
    Ruby. Lots of things happen that are impossible to understand without
    understanding that principle.

    As for instance variables: each and every instance variable belongs to
    a particular object, and every object is an instance of some class.

    class C
    @x = 1 # an instance variable of the object C, which is
    # an instance of Class
    def meth
    @x = 1 # an instance variable of any instance of C that
    end # calls this method

    end

    The ownership of instance variables is governed by what object is
    playing the role of "self" at the point when the instance variable is
    encountered. The object may, indifferently, be an instance of Class,
    an instance of String, an instance of MyClass, and so on.

    The term "class instance variable" is completely inappropriate, and
    potentially very confusing, as a synonym for "instance variable".


    David

    --
    David A. Black |
    Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
    DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
    [1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
    [2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
     
    dblack, Dec 6, 2006
    #8
  9. Andreas Warberg

    dblack Guest

    No; the discussion is about instance variable that belong to class
    objects (i.e., instances of Class). Dave makes the distinction
    between "class instance variables" and "regular instance variables"
    for the sake of pointing up, ultimately, the fact that classes, as
    instances, can have instance variables.

    At no point does Dave suggest or imply that "class instance variable"
    is an appropriate universal term for @this kind of variable.


    David

    --
    David A. Black |
    Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
    DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
    [1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
    [2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
     
    dblack, Dec 6, 2006
    #9
  10. Andreas Warberg

    Eric Hodel Guest

    I'm sorry if you've spent your time trapped in crappy OO languages
    like Java and C++ where classes aren't real objects.
    ruby disagrees with your opinion:

    ruby -e 'p Object.class; p Object.ancestors'
    Class
    [Object, Kernel]

    As does "ri Class".
    What the pickaxe refers to as "class instance variables" are
    "instance variables of a Class". There is no difference in instance
    variables no matter which object they live in. Clinging futilely to
    some believe that there is some difference will only limit your
    understanding of Ruby.
     
    Eric Hodel, Dec 6, 2006
    #10
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.