toddddos
toddddos

Reputation: 361

Value not displayed when returned as array

I have this piece of code

class Test
  def self.testme(a, b)
    @arr = [@x, @y]
    if (a == 0)
      if (b == 0)
        return nil
      else
        @x = a * b
        return @arr[0]
      end
    end
    ...# @y needed in other part below
  end
end

and want to return the array with the corresponding value (either result in @x or @y) so that the result is [12] when 3 and 4 are input.

But I get nil when I use return @arr[0], or [nil] when using return @arr[0,1]. When I return just @arr the result is something like [12, nil] even though there should be something in @y

Returning only @x or @y works, but doesn't solve my problem. How can I make this work?

Upvotes: 0

Views: 37

Answers (1)

Neil Slater
Neil Slater

Reputation: 27207

The line

@arr = [@x, @y]

is not doing quite what you think it does. It does not create an Array with maintained references to the variables @x, @y. Instead it creates an Array containing the current values of @x and @y. (See footnote)

Therefore, when you change the object that @x or @y point to, as in the line @x = a * b, this does not affect @arr.

The simple fix, if you want to return an array containing the final values of @x and @y, is to construct and return that array at the end, in order to return it. You probably don't need @arr at all in order to do that.

Just

return [@x, @y]

would do that. If that is at the very end of your method, then it is Ruby convention to omit the return and just have

[@x, @y]

If for some reason, you really do need to maintain the @arr variable and return @arr[0] as per your example, then you will need to set @arr just before you return it e.g.

  else
    @x = a * b
    @arr = [@x, @y]
    return @arr[0]
  end

or even

  else
    @arr = [a * b, @y]
    return @arr[0]
  end

if @x is supposed to be internal to the method (in which case, BTW, you would be better off calling it just x if it needs to hold some temporary working values)


Footnote: In Ruby it is important to track the distinction between variables and the objects they point to. It is because you re-assign the variable @x that you see the results that you do. When you use more complex objects, such as Strings or Arrays, and modify them in place (e.g. for a String use @x.gsub!( /foo/, 'bar' )) then you may be able to use the technique of setting up the return structure at the beginning and adjusting it.

Upvotes: 3

Related Questions