Understanding Areas in Ruby

I am trying to deal with a very strange (at least to me) situation in Ruby. My code is as follows:

class ScopeTest attr_accessor :flag def flagtest puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s if flag == 1 flag = 0 puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s self.flag = 0 puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s flagtest else puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s end end end st = ScopeTest.new st.flag = 1 st.flagtest 

And the conclusion is as follows:

 SELF: 1 INST: 1 SELF: 1 INST: 0 SELF: 0 INST: 0 SELF: 0 INST: 0 SELF: 0 INST: 

What is strange that the flag variable is nil the last time I print it (inside else ), but 0 right before that (before if...else in the flagestest method)?

When I delete a few lines of code, everything seems normal, like the following code:

 class ScopeTest attr_accessor :flag def flagtest puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s if flag == 1 self.flag = 0 puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s flagtest else puts "SELF: " + self.flag.to_s puts "INST: " + flag.to_s end end end st = ScopeTest.new st.flag = 1 st.flagtest 

gives the following result:

 SELF: 1 INST: 1 SELF: 0 INST: 0 SELF: 0 INST: 0 SELF: 0 INST: 0 

Any clues as to what is happening and why?

+4
source share
3 answers

flag = 0 creates a local variable called a flag whose scope reaches the end of the method. Any use of flag that appears lexically after this assignment refers to a local variable. Any previous view (as well as any appearance of self.flag ) refers to the getter method.

So, flag in else refers to a local variable. Since a local variable never received a value in an else branch, its value is nil .

+2
source

This is because you have the local variable flag = 0 assigned. IIRC, local variables are created during parsing and are tied to a method. By default, they are initialized to nil . So in your sentence then you assign it a value before it is available. But when you enter the method again, you go to else , and the flag remains uninitialized (i.e. nil ).

 class ScopeTest attr_accessor :flag def flagtest # if you comment this line, the method will output 1, 1 # if you don't comment, it will output 1, nil, because the assignment to local variable was never done. # but local var itself was created. flag = 3 if false puts self.flag.inspect puts flag.inspect end end st = ScopeTest.new st.flag = 1 st.flagtest # >> 1 # >> nil 
+3
source

See reason: -

 class ScopeTest attr_accessor :flag def flagtest p defined?(flag) if flag == 1 p defined?(flag) flag = 0 p defined?(flag) self.flag = 0 flagtest else p defined?(flag) end end end st = ScopeTest.new st.flag = 1 

Exit

 "method" "method" "local-variable" "method" "local-variable" 
+2
source

Source: https://habr.com/ru/post/1500172/


All Articles