user3476791
user3476791

Reputation: 1092

An easy Ques from a beginner of Ruby

I got the following error message

NameError: undefined local variable or method a' for main:Object from (irb):2 from /usr/local/bin/irb:12:in'

if my code was as follows:

[1,2,3].each{|x| a=x}
puts x

However, if I put one sentence at the beginning of the script, everything was OK.

a=nil

Would anyone tell me why 'a=nil' is necessary? Thanks!

Upvotes: 0

Views: 62

Answers (1)

Arup Rakshit
Arup Rakshit

Reputation: 118261

[1,2,3].each{|x| a = x} 
puts a

Here you have created a inside the block. So a is only accessible inside the block. Outside world don't know who is a. a is lexically scoped to block. Thus when, you are trying to use a before introducing it to the outside scope of the block, MRI complaining about a. If you try to access x also, you will be having the same complains from MRI.

[1].each do |x|
  a = x 
  local_variables # => [:x, :a]
end

local_variables # => []

a = nil
[1,2,3].each{|x| a = x} 
puts a

Now you created a outside the block, which is top level. Now #each method takes a block { |..| ... }. Blocks are closure in Ruby, i.e. it has access to the outside variables, which are created before the block is defined. Inside the block, you can access the a, which you defined outside and update it also. Now when bock will be ended its execution, you can see the last updated value of a. *But if you try to access x, you will get the same error/complains from MRI as you got above.* - The reason being, x lexically scoped to the block, where you have created it firs time, outer scope, ie, outside the block, it has no existence.

a = nil
[1].each do |x|
  a = x
  local_variables # => [:x, :a]
end

local_variables # => [:a]

Upvotes: 2

Related Questions