# Variable / Method Ambiguity

**URL:** <https://www.ruby-forum.com/t/variable-method-ambiguity/114592>\
**Category:** Ruby\
**Created:** [September 17, 2007, 3:18am UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592 "2007-09-17T03:18:38Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 17, 2007, 3:18am UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/1 "2007-09-17T03:18:38Z")

</div>

the following program for showing Variable / Method Ambiguity

def a  
print “Function ‘a’ called\n”  
99  
end

for i in 1…2  
if i == 2  
print “a=”, a, “\n”  
else  
a = 1  
print “a=”, a, “\n”  
end  
end

will produce the result:

a=1  
Function ‘a’ called  
a=99

(as described in the PickAx2 book, p. 329)

So at first I thought a Ruby program is interpreted? If interpreted,  
then the interpreter will see the “a = 1” at first as treat “a” as a  
variable, and then the second time it sees “a”, the interpreter should  
treat it as a variable again, not as a method. So does that mean a  
Ruby program is not interpreted but compiled into some bytecode first?  
But then, sometimes I run a Ruby program and then it can run all the way  
until it see an “undefined local variable”… so that means it probably  
is not compiled… or else it would have stopped without running  
anything at all.

So is a Ruby program interpreted or compiled?

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 17, 2007, 9:00am UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/2 "2007-09-17T09:00:20Z")

</div>

> So is a Ruby program interpreted or compiled?

interpreted.

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 17, 2007, 11:53am UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/3 "2007-09-17T11:53:48Z")

</div>

On Sep 17, 12:49 am, “David A. Black” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> No, because there’s no such variable in scope. The second time through  
> the loop, there’s no assignment to a, and the first variable a has  
> gone out of scope. So the only thing that “a” could mean, outside of  
> an assignment, is the method a.

wow… i thought the “a” variable is kind of like in C or Python:

for (i = 1; i \<= 2; i++) {  
int a;

if (i==2) {  
…  
} else {  
…  
}

}

so that the “a” exists all inside the for loop… maybe that’s not  
right.

now, we can view the variable “a” as existing in the else block but no  
where else in the original Ruby code?

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 17, 2007, 1:23pm UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/4 "2007-09-17T13:23:28Z")

</div>

Hi –

On Mon, 17 Sep 2007, Summercool Summercool wrote:

> else
> 
> (as described in the PickAx2 book, p. 329)
> 
> So at first I thought a Ruby program is interpreted? If interpreted,  
> then the interpreter will see the “a = 1” at first as treat “a” as a  
> variable, and then the second time it sees “a”, the interpreter should  
> treat it as a variable again, not as a method.

No, because there’s no such variable in scope. The second time through  
the loop, there’s no assignment to a, and the first variable a has  
gone out of scope. So the only thing that “a” could mean, outside of  
an assignment, is the method a.

David

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 17, 2007, 4:30pm UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/5 "2007-09-17T16:30:37Z")

</div>

Summercool Summercool wrote:

> So is a Ruby program interpreted or compiled?  
> It is interpreted but before being interpreted it is parsed. And whether  
> a symbol is a variable or not is determined at parse time: when the  
> parser sees the assignment “a = 1”, it assumes that ‘a’ is a variable  
> for all subsequent _lines_ of the source code, until the end of the  
> method or block where the assignment occured. It is has nothing to do  
> with the order in which the code is executed.

Also you’ll notice that the “undefined local variable” message is  
actually “undefined local variable or method”, because ruby can’t know  
if the unknown symbol was supposed to be a method or a variable.

Daniel

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 17, 2007, 6:10pm UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/6 "2007-09-17T18:10:52Z")

</div>

On 9/17/07, David A. Black [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > variable, and then the second time it sees “a”, the interpreter should  
> > treat it as a variable again, not as a method.
> 
> No, because there’s no such variable in scope. The second time through  
> the loop, there’s no assignment to a, and the first variable a has  
> gone out of scope.

so this is lexical scoping, then?

> So the only thing that “a” could mean, outside of  
> an assignment, is the method a.
> 
> David

-jf

–  
In the meantime, here is your PSA:  
“It’s so hard to write a graphics driver that open-sourcing it would not  
help.”  
– Andrew Fear, Software Product Manager, NVIDIA Corporation

> **[An Interview With Linus Torvalds: Linux and Git - Part 1 30 Years Of Linux](https://www.tag1consulting.com/blog/interview-linus-torvalds-linux-and-git)**
>
> Thirty years ago, Linus Torvalds was a 21 year old student at the University of Helsinki when he first released the Linux Kernel. His announcement started, “I’m doing a (free) operating system (just a hobby, won't be big and professional…)”. Three...

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 18, 2007, 9:08pm UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/7 "2007-09-18T21:08:43Z")

</div>

On Sep 17, 2007, at 12:08 PM, Jeffrey ‘jf’ Lim wrote:

> > > interpreted,  
> > > so this is lexical scoping, then?  
> > > No, it is just that Ruby has a single-pass parser. The parser needs  
> > > to decide if an identifier is a local variable or a zero-argument method  
> > > before it has seen the entire text of the file (no look-ahead). Until  
> > > the parser sees an assignment of the form “a = …” it assumes  
> > > that ‘a’ is a method call.

So if/then/else statements do _not_ create new lexical scopes.

Gary W.

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 18, 2007, 10:21pm UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/8 "2007-09-18T22:21:23Z")

</div>

7stud – wrote:

> David Black wrote:  
> The second time through  
> the loop, there’s no assignment to a, and the first variable a has  
> gone out of scope. \>

Wait a minute. ‘a’ has gone out of scope?

for i in 1…2  
if i == 1  
a = 10  
print “a=”, a, “\n”  
else  
puts a  
end  
end

puts “\*#{a}”

puts a

–output:–  
a=10  
10  
\*10

In ruby, for loops and if clauses don’t create a scope.

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 18, 2007, 10:11pm UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/9 "2007-09-18T22:11:45Z")

</div>

David A. Black wrote:

> No, because there’s no such variable in scope. The second time through  
> the loop, there’s no assignment to a, and the first variable a has  
> gone out of scope. So the only thing that “a” could mean, outside of  
> an assignment, is the method a.

That doesn’t seem to bear out. If you switch the if statement around so  
that the assignment happens first:

def x  
print “Function ‘x’ called\n”  
99  
end

for i in 1…2  
if i == 1  
x = 10  
print “x=”, x, “\n”  
else  
print “x=”, x, “\n”  
end  
end

the output is:

x=10  
x=10

The second time through that loop, there is no assignment to x and the  
previous x has gone out of scope, yet the else clause’s use of x does  
not result in a method call.

As p. 329 in pickaxe2 carefully explains, it is a ruby parsing rule that  
determines what x means. As I read the rule, and as Daniel explains,  
and as the two examples show(the ‘a’ example and the ‘x’ example), the  
rule is: if there is any code that has x=val on a line before the use of  
x, then x will be interpreted as a variable. If there is no assignment  
to x on a line higher in the code, then x will be interpreted as a  
method call.

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 19, 2007, 4:51am UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/10 "2007-09-19T04:51:29Z")

</div>

From: 7stud – [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]

# In ruby, for loops and if clauses don’t create a scope.

irb(main):001:0\> if false  
irb(main):002:1\> x  
irb(main):003:1\> end  
=\> nil  
irb(main):004:0\> x  
NameError: undefined local variable or method `x’ for main:Object  
from (irb):4  
irb(main):005:0\> if false  
irb(main):006:1\> x = 5  
irb(main):007:1\> end  
=\> nil  
irb(main):008:0\> x  
=\> nil

they can introduce a var (under the existing local scope of course).  
i think its in the assignment behaviour if you look at it. parser sees  
assignment even if code is not executed.  
ruby just try to be friendly, but you can be sloppy if you want to and  
ruby will not give you an error 🙂  
again, i think this is a faq.

kind regards -botp

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [September 18, 2007, 10:37pm UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/11 "2007-09-18T22:37:53Z")

</div>

7stud – wrote:

> That doesn’t seem to bear out. If you switch the if statement around so  
> that the assignment happens first:
> 
> def x  
> print “Function ‘x’ called\n”  
> 99  
> end

The difference between the both examples is the following:

Ruby parses this:

for i in 1…2  
if i == 2  
print “a=”, a, “\n”

> > Here Ruby decides, that “a” must mean the a method and creates the call-method node in its tree.  
> > else  
> > a = 1
> 
> > Here Ruby decides, a is a local variable.  
> > print “a=”, a, “\n”
> 
> > Here Ruby creates a evaluate-local-variable node in its tree.  
> > end  
> > end

In your example:

> for i in 1…2  
> if i == 1  
> x = 1
> 
> > Here Ruby decides, “x” is a local variable.

> ```
> print "x=", x, "\n"
> 
> ```
> 
> > Here Ruby creates a evaluate-local-variable node in its tree.

> ```
> else
> print "x=", x, "\n"
> 
> ```
> 
> > Sticks to its former decision, that “x” is local variable, and  
> > creates a evaluate-local-variable node in its tree.  
> > end  
> > end

This is an interaction between parsing and execution or ruby code, and  
it can be a bit surprising. The later execution (== comparisons, etc.)  
doesn’t alter the behavior of the parser, which does its jobs earlier.

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [December 9, 2007, 10:43pm UTC](https://www.ruby-forum.com/t/variable-method-ambiguity/114592/12 "2007-12-09T22:43:17Z")

</div>

Hi,

7stud – wrote:

> David A. Black wrote:

> As p. 329 in pickaxe2 carefully explains, it is a ruby parsing rule that  
> determines what x means. As I read the rule, and as Daniel explains,  
> and as the two examples show(the ‘a’ example and the ‘x’ example), the  
> rule is: if there is any code that has x=val on a line before the use of  
> x, then x will be interpreted as a variable. If there is no assignment  
> to x on a line higher in the code, then x will be interpreted as a  
> method call.

Please, look at this 2 examples of “parse-time”:  
1)

> pp ParseTree.translate(‘bar = 3  
> define\_method(:foo) do  
> bar  
> end’)  
> [:block,  
> [:lasgn, :bar, [:lit, 3]],  
> [:iter, [:fcall, :define\_method, [:array, [:lit, :foo]]], nil, [:lvar,  
> :bar]]]

1. 

> pp ParseTree.translate(‘bar = 3  
> def foo  
> bar  
> end’)  
> [:block,  
> [:lasgn, :bar, [:lit, 3]],  
> [:defn, :foo, [:scope, [:block, [:args], [:vcall, :bar]]]]]

* * *

In 1) we see a :lvar node, whereas in 2) we see a :vcall. From my  
interpretation of p.329 of pickaxe2 i do not agree with the 2nd case  
(but probably it’s my problem - comment please). In the 2nd case, IMHO,  
we should see a lvar node.  
This may seem a detail, but i was bitten by that a few minutes ago. Let  
me show a simplified example:

bar = “test”  
c = Class.new  
c.class\_eval do  
def foo  
bar  
end  
end

> c.new.foo  
> NameError: undefined local variable or method `bar’

# i was expecting to get “test”

The (hack) “solution” (it’s a hack because IMHO i shouldn’t have to do  
that):  
bar = “test”  
c = Class.new  
c.class\_eval do  
define\_method(:foo) do  
bar  
end  
end

> c.new.foo  
> “test”

Note: only one more thing, since ruby 1.8 have a “problem” with block  
(it can’t get other blocks - &block in argument) this could be a  
problem. I know you can hack these thing through a method - but that’s  
another hack :P… too much hacks for me 🙂

I would appreciate very much all your comments about the current  
behavior of ruby (1.8).

Regards,  
Vasco Andrade e Silva
