Newbie question re. blocks & variable scope

S

Steve Cooper

Hi,

I'd like to ask for some help with local variable scope. I understand
that the scope of a local variable is the "do...end" block in which it
is created. However, the code below shows that the value assigned to
the variable within a block does not persist after the single
iteration in which the variable is given that value, although the
variable is still defined in a later iteration. That is, in the idx=2
iteration, Ruby does not remember that a=11 in the previous iteration,
but it also does not complain about an undefined local variable "a"
(which it of course does outside the block). I haven't been able to
find this behavior mentioned in the documentation or in this
group--can you point me to something that will clarify for me what is
going on?

Thanks,
Steve

data=[1,2]
data.each do | idx|
if idx == 1
a = 11
print "idx=1: a=",a,"\n"
elsif idx == 2
b = 12
print "idx=2: a=",a," b=",b,"\n"
end
end
print "after:\n"
print "a=",a," b=",b,"\n"
c:\ruby\bin\ruby test.rb
idx=1: a=11
idx=2: a=nil b=12
after:
test.rb:12: undefined local variable or method `a' for main:Object
(NameError)
 
S

Shashank Date

Steve Cooper said:
I'd like to ask for some help with local variable scope. I understand
that the scope of a local variable is the "do...end" block in which it
is created.

Correct (so far ;-) !
However, the code below shows that the value assigned to
the variable within a block does not persist after the single
iteration in which the variable is given that value, although the
variable is still defined in a later iteration.

Ah ha ! You are using the term _iteration_ to mean a
"looping construct" (control structure) and then in the example
using "each" which is an "iterator" (method).

In Ruby, a looping construct is _not the same_ as an iterator.
An iterator may be implemented using "yield" and some form
of a looping construct. This is nicely explained in Pickaxe.
That is, in the idx=2 iteration, Ruby does not remember
that a=11 in the previous iteration,
but it also does not complain about an undefined local variable "a"
(which it of course does outside the block).

Which is because you are using each (iterator).
I haven't been able to
find this behavior mentioned in the documentation or in this
group--can you point me to something that will clarify for me what is
going on?

Read the later half of Chapter 7 of PickAxe carefully, esp. the sub-topics
"Loops" onwards.
data=[1,2]
data.each do | idx|
if idx == 1
a = 11
print "idx=1: a=",a,"\n"
elsif idx == 2
b = 12
print "idx=2: a=",a," b=",b,"\n"
end
end
print "after:\n"
print "a=",a," b=",b,"\n"


If you rewrite this using a _looping construct_ such as

#----------------------
data=[1,2]
for idx in data
if (idx == 1)
a = 11
puts "idx=#{idx}: a=#{a}"
elsif (idx == 2)
b = 12
p "idx=#{idx}: a=#{a} b=#{b}"
end
end
#----------------------

then you should get the desired behavior.

Does that make sense ?

-- shanko
 
K

Kenta MURATA

In message <[email protected]> at Mon, 19 Jan 2004 04:10:03 +0900,
I'd like to ask for some help with local variable scope. I understand
that the scope of a local variable is the "do...end" block in which it
is created. However, the code below shows that the value assigned to
the variable within a block does not persist after the single
iteration in which the variable is given that value, although the
variable is still defined in a later iteration. That is, in the idx=2
iteration, Ruby does not remember that a=11 in the previous iteration,
but it also does not complain about an undefined local variable "a"
(which it of course does outside the block). I haven't been able to
find this behavior mentioned in the documentation or in this
group--can you point me to something that will clarify for me what is
going on?

Local variable is defined when it is parsed. And block
internal scope is initialized each block call. That is, in
the idx == 2 iteration, Ruby do:

(1) initialize block internal scope.
(2) parse ``a = 11'' line and define variable `a'.
(3) reference varaible `a', but it is not initialized (== nil).
data=[1,2]
data.each do | idx|
if idx == 1
a = 11
print "idx=1: a=",a,"\n"
elsif idx == 2
b = 12
print "idx=2: a=",a," b=",b,"\n"
end
end
print "after:\n"
print "a=",a," b=",b,"\n"
c:\ruby\bin\ruby test.rb
idx=1: a=11
idx=2: a=nil b=12
after:
test.rb:12: undefined local variable or method `a' for main:Object
(NameError)
Exit code: 1
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top