1. Computing

Block Variable Scope in Ruby 1.9.x

Changes in Block Variable Scope

By

With the release of Ruby 1.9.1, there are some new features to learn, including some changes in block variable scope. In Ruby 1.9.1, the way blocks are implemented internally and are used in your code has changed. Don't worry, all the good stuff is still there with some minor modifications, but there are some new features and caveats.

In Ruby 1.8.x, block variables were introduced into the scope that the block was called from. Now, in Ruby 1.9.1, blocks introduce their own scope for the block parameters only. That means, when a block taking a single parameter called x is called, if there are local variables x and y in scope, then any reference to the variable x within the scope refers to the new variable the block parameter brings into scope. However, any reference to the variable y in the block refers to the variable y in scope where the block was called. If that sounds confusing, just look at this code--it should be clearer.

In the code, the local variable x is given the value 1337. The first block to be executed in this scope has a parameter named x. The x variable inside the block refers to the new x variable introduced by the block. Any method calls on x, assignments to x, etc., will refer to the new x variable, and not the x variable outside the block.

However, in the second block, the block parameter is named y. Each time the variable x is referred to inside the second block, it's referring to the x outside of the block since there is no parameter called x. So when x is assigned to, the x outside of the block is being assigned to.

In the third block, a new feature is being used: block local variable. In short, block local variables shield a block from manipulating variables outside of its scope. This prevents a block from unintentionally clobbering any variables outside its scope. If you don't want to clobber variables, use block local variables for the variables your block creates.

The syntax for a block local variable is simple. Put a semicolon after the normal block parameter list, then list the variable you want as block local variables. For example, if the block takes two variables a and b, and uses to local variables x and y, the parameter list would look like this: |a,b; x,y|.

 #!/usr/bin/env ruby
 
 # First block
 x = 1337
 puts "Before the loop, x = #{x}"
 
 3.times{|x| puts "Looping #{x}" }
 
 puts "After the loop, x = #{x}"
 puts '-' * 20
 puts
 
 # Second block
 x = 1337
 puts "Before the loop, x = #{x}"
 
 3.times do|y|
 puts "Looping #{y}"
 x = y
 end
 
 puts "After the loop, x = #{x}"
 puts '-' * 20
 puts
 
 # Third block
 x = 1337
 puts "Before the loop, x = #{x}"
 
 3.times do|y;x|
 puts "Looping #{y}"
 x = y
 end
 
 puts "After the loop, x = #{x}"
 
 Before the loop, x = 1337
 Looping 0
 Looping 1
 Looping 2
 After the loop, x = 1337
 --------------------
 
 Before the loop, x = 1337
 Looping 0
 Looping 1
 Looping 2
 After the loop, x = 2
 --------------------
 
 Before the loop, x = 1337
 Looping 0
 Looping 1
 Looping 2
 After the loop, x = 1337
 

Feb. 2009

  1. About.com
  2. Computing
  3. Ruby
  4. Beginning Ruby
  5. New in Ruby 1.9.x
  6. Block Variable Scope

©2014 About.com. All rights reserved.