L_G
L_G

Reputation: 209

Ruby block variable scope within/out the method

I get the following different results:

Test 1:

def myblock
  x = 1
  y = 1
  yield(x)
  [x, y]
end

myblock do |x|
 y = 10
end
# => [1,1]

Test 2:

x = 1
y = 1

1.upto(2) do |x|
  y = 20
end
[x,y]
# => [1,20]

Variables created outside the block are available in the block. Why are they so?

Upvotes: 0

Views: 436

Answers (3)

L_G
L_G

Reputation: 209

After more testing and searching:

For Test1, x and y is method level local variable and they don't share the scope with block. y in the block is a new local variable(block level).

For Test2, x and y is class level local variable and they share the scope with block, y in the block is still the outside y(class level).

It's all because I messed up the scope, thanks all.

Upvotes: 0

Cary Swoveland
Cary Swoveland

Reputation: 110685

def myblock
  x = 1
  y = 1
  z = yield(x)
  puts "y=#{y}, z=#{z}"
  [x, y]
end

myblock do |x|
 y = 10
end
y=1, z=10
  #=> [1, 1]

This shows that three things are going on here:

  • The y in the block is unrelated to the y in myblock. That's because the scope of the y in the block is confined to the block. Ruby can only get her hands on what is returned by the block, not on what's going on inside of it.
  • The block does indeed return the value of y in the block, but only because y = 10 was the last statement executed in the block. The execution of that statement returns 10, so 10 is returned by the block. Had the block contained y = 10; 7, 7 would have been returned.
  • The value of yield(x) is not captured by the variable y in myblock, so it has no effect.1.

1 It's a little-known fact that Ruby actually shoots such values into outer space.

Upvotes: 1

sawa
sawa

Reputation: 168101

That is how the scope of a local variable is defined. A local variable can percolate into a block, but not into a method definition.

Upvotes: 2

Related Questions