robert williams robert williams - 2 months ago 12
Ruby Question

confused between instance variable and local variable

I recently started learning ruby and i am confused between instance variable and local variable and class variable. so , i recently written code which will find the largest palindrome in 1000 prime numbers.
code is:

def prime_large(number)
arr_prime = []
Prime.each(number) do |x|
new_arr_prime = arr_prime.push(x.to_s)
updated = new_arr_prime.select { |y| y.reverse == y }
end
p updated.max
end
p prime_large(1000)


error i got is:

undefined local variable or method `updated' for main:Object (NameError)


I know that updated is a local variable of prime so i can't access it outside it but i changed the code by replacing it with @updated as below:

def prime_large(number)
arr_prime = []
Prime.each(number) do |x|
new_arr_prime = arr_prime.push(x.to_s)
@updated = new_arr_prime.select { |y| y.reverse == y }
end
p @updated.max
end
p prime_large(1000)


after changing it , i got the output:

"929"
"929"


in my code , without creating a class how my instance variable ( @updated) is working . i am confused between local and instance variable . can anyone please explain me the differences and how they work ?

Answer

In your first example you created a local variable updated, that is only accessible within the scope of the block it is defined in. Meaning, it is available only within Prime.each(number) do end block.

In your second example you created instance variable @updated.

without creating a class how my instance variable ( @updated) is working

It is because in Ruby everything occurs in the context of some object. Even though you did not created a class, you are being in the top-level context, in the context of object main.

Thus, any instance variables defined within top-level are instance variables of this object main.

So going back to your issue, to overcome it you'll want to just define the updated local variable outside the Prime.each(number) do end block:

def prime_large(number)
  arr_prime = []
  updated   = nil # initialize local varialbe
  Prime.each(number) do |x|
    new_arr_prime = arr_prime.push(x.to_s)
    updated = new_arr_prime.select { |y| y.reverse == y } # assign new value
  end
  p updated.max 
end
p prime_large(1000)

To test it you can open irb or pry and check it yourself:

self               # the object in the context of which you are currently
#=> main
self.class         # main is an instance of class Object, any methods defined
                   # within main are added to Object class as instance methods
#=> Object
instance_variables # list of it's instance variables, none yet created
#=> []
@variable = 1      # create and instance variable
#=> 1
instance_variables # now created variable occurs in the list of current object's instance variables
#=> [:@variable]
def hello; :hello end # define method
#=> :hello
self.class.public_instance_methods(false) # list instance methods defined in Object
#=> [:hello]

What you now want to read about is lexical scopes in Ruby.