Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How come (a_method || :other) returns :other only when assigning to a var called a_method?

Tags:

ruby

Given the following method:

def some_method
  :value
end

The following statements work as I would expect:

some_method || :other
# => :value

x = some_method || :other
# => :value

But the behaviour of the following statement perplexes me:

some_method = some_method || :other
# => :other

It creates a local variable called some_method as expected, and subsequent calls to some_method return the value of that local variable. But why does it assign :other rather than :value?

I understand that it's probably not a smart thing to do, and can see how it might be ambiguous, but I thought the right-hand-side of the assignment should be evaluated prior to the assignment being considered...

I've tested this in Ruby 1.8.7 and Ruby 1.9.2 with identical results.

Cheers!

Paul

like image 852
Paul Annesley Avatar asked Jan 13 '11 09:01

Paul Annesley


2 Answers

There have been similar questions, but not exactly the same. Jörg's answer here seems to hit the point, I'm quoting the relevant part:

At this point, foo is defined, even though the line will never get executed. The fact that the line never gets executed is completely irrelevant, because the interpreter has nothing to do with this anyway: local variables are defined by the parser, and the parser obviously sees this line.

So, in your case, regardless of the fact that a method with the same name already exists, the parser sees some_method assignment and it automatically "tags" the identifier to be local variable. So, when interpreter starts evaluating the right-hand-side of the assignment, it already considers some_method to be local variable, not a method. Its value is unassigned (nil by default), so the result of || will be :other.

like image 58
Mladen Jablanović Avatar answered Nov 10 '22 05:11

Mladen Jablanović


A simple answer is: your last statement is the same as

some_var = some_var || :other

because when you have a local variable in scope with the same name as a method, the interpreter gives the local variable precedence.

like image 4
Mark Thomas Avatar answered Nov 10 '22 05:11

Mark Thomas