Reputation: 1092
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
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