Reputation: 209
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
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
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:
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.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.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
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