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