Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

method's local variable with same name as another method

Tags:

ruby

I was trying to figure out how Ruby handles local variables that have the same names as the methods in self class, and found a behavior that I do not understand:

class A
  def val
    10
  end

  def test
    val = val
  end
end

p A.new.test

this code prints nil. why?!

like image 810
akonsu Avatar asked Apr 03 '13 14:04

akonsu


People also ask

Is it OK to give the same name to variables in different methods?

In a word, yes. Variable names only hold in the scope they're defined in, and you can use the same name in different scopes.

Is it legal to declare two variables with the same name in the same method in such a way that their scopes overlap?

You cannot declare two variables with the same name in the same scope.

Can local variable have same name as instance variable?

Answer: Yes — the scopes will not overlap so there will be two local variables, one per method, each with the same name.

Can two local variables have the same name?

It is usually not a good programming practice to give different variables the same names. If a global and a local variable with the same name are in scope, which means accessible, at the same time, your code can access only the local variable.


2 Answers

I think that the local variable is declared as soon as it's enunciated. In ruby the lookup is first to look for a local variable, if it exists it's used, and if not it looks for a method. This would mean that val = val declares the first val as local and the left-hand val then matches it (not sure about it I should check the ruby under microscope to be sure)

If you try

class A
  def val
    10
  end

  def test
    back = []
    x = val
    back << x
    val = x + 1
    back << val
    x = val
    back << x
  end
end

p A.new.test

then all is good, it prints [10, 11, 11] which means the first x = val calls the method, the second calls the local variable, presumably.

like image 160
Mose Avatar answered Sep 27 '22 18:09

Mose


The other answers explain everything fine I just want to point readers with the same problem to the official documentation about this.

Local Variables and Methods

In Ruby local variable names and method names are nearly identical. If you have not assigned to one of these ambiguous names ruby will assume you wish to call a method. Once you have assigned to the name ruby will assume you wish to reference a local variable.

The local variable is created when the parser encounters the assignment, not when the assignment occurs:

a = 0 if false # does not assign to a

p local_variables # prints [:a]

p a # prints nil

The similarity between method and local variable names can lead to confusing code, for example:

def big_calculation
  42 # pretend this takes a long time
end

big_calculation = big_calculation()

Now any reference to big_calculation is considered a local variable and will be cached. To call the method, use self.big_calculation.

You can force a method call by using empty argument parentheses as shown above or by using an explicit receiver like self. Using an explicit receiver may raise a NameError if the method's visibility is not public or the receiver is the literal self.

Another commonly confusing case is when using a modifier if:

p a if a = 0.zero?

Rather than printing “true” you receive a NameError, “undefined local variable or method `a'”. Since ruby parses the bare a left of the if first and has not yet seen an assignment to a it assumes you wish to call a method. Ruby then sees the assignment to a and will assume you are referencing a local method.

The confusion comes from the out-of-order execution of the expression. First the local variable is assigned-to then you attempt to call a nonexistent method.

like image 30
3limin4t0r Avatar answered Sep 27 '22 18:09

3limin4t0r