Newbie question re. blocks & variable scope

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)

···

Exit code: 1

“Steve Cooper” stevec890@yahoo.com wrote in message

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 :wink: !

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

In message a07f3c32.0401181107.687aea8b@posting.google.com at Mon, 19 Jan 2004 04:10:03 +0900,
stevec890@yahoo.com (Steve Cooper) wrote:

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


1024D/2A3FDBE6 2001-08-26 Kenta MURATA (muraken) muraken2@nifty.com
Key fingerprint = 622A 61D3 280F 4991 4833 5724 8E2D C5E1 2A3F DBE6