# Counter Inside a Block?

Hello!

When inside a block, do I have access to a local integer counter from 0
up to whatever the length of the collection, like this:

%w[
Hamster
Zebra
Wolf
].each do|a|
puts “Warning Number #{\$CURRENT}: a #{a} is a dangerous animal!”
end

OUTPUT

Warning Number : a Hamster is a dangerous animal!
Warning Number : a Zebra is a dangerous animal!
Warning Number : a Wolf is a dangerous animal!

so that I can refer to the warning by number, when one of the feared
animals shows up.

You can do it like this:

%w[ Hamster Zebra Wolf ].each_with_index do |a,index|
puts “Warning Number #{index}: a #{a} is a dangerous animal!”
end

#-----------------------------------------------------
Warning Number 0: a Hamster is a dangerous animal!
Warning Number 1: a Zebra is a dangerous animal!
Warning Number 2: a Wolf is a dangerous animal!
#-----------------------------------------------------

If you want the index begin from 1, do this:

%w[ Hamster Zebra Wolf ].each.with_index(1) do |a,index|
puts “Warning Number #{index}: a #{a} is a dangerous animal!”
end

#-----------------------------------------------------
Warning Number 1: a Hamster is a dangerous animal!
Warning Number 2: a Zebra is a dangerous animal!
Warning Number 3: a Wolf is a dangerous animal!
#-----------------------------------------------------

Agent M. wrote in post #1006092:

Hello!

When inside a block, do I have access to a local integer counter

What do you mean by ‘local’?

[1, 2, 3]. each do |num|
counter = 1
puts counter #yes, puts() can see the local variable counter
end

–output:–
1
1
1

Other locations for counter can easily be tested:

counter = 0

[1, 2, 3]. each do |num|
counter += 1
puts counter
end

–output:–
1
2
3

Blocks ‘close’ over the variables that can be seen at the time the block
is created. Thereafter, the block consults those variables for their
values. Here is an example:

x = 1
y = 3

my_function = Proc.new {|arg| (x + y) * arg}

#def’s create a new scope, cutting off the visibility of the outer scope

def do_stuff(func)
x = 10 #this x variable is not the same variable as the outer x
y = 30 #this y variable is not the same variable as the outer y

func.call(2)
end

result = do_stuff(my_function)
puts result

–output:–
8

Compare to this:

x = 1
y = 3

my_function = Proc.new {|arg| (x + y) * arg}
#closes over outer x, y variables

x = 10 #changes outer x
y = 30 #changes outer y

result = my_function.call(2)
puts result

–output:–
80

If you ever have problems with a block getting the wrong values for
variables, look back in your code to where the block was created(i.e.
where it was
written in your code by you), and write down all the variables(and their
values) that the block
can see at that point in your code. Those are the variables that the
block sees when it executes.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.