2

I've been working on Ruby Koans and I've gotten to this part that I don't understand too well. Specifically, it's the about_dice_project, where they ask us to define a class to pass several pre-set tests. Originally, my class looked like

class DiceSet
    attr_accessor :values
    def initialize
        @values = []
    end
    def roll(num)
        num.times { |i| @values[i] = rand(1..6) }
        return @values
    end
end

But this failed the test below

dice = DiceSet.new

dice.roll(5)
first_time = dice.values

dice.roll(5)
second_time = dice.values

assert_not_equal first_time, second_time,
  "Two rolls should not be equal"

And I realized after some testing that both first_time and second_time have the same object_id. So I looked on stackoverflow for some help and found this answer, which doesn't answer my question directly, but I did find a major difference in our code; namely, that instead of using the "num.times" way of rolling the dice, goes instead with

@values = Array.new(num) { rand(1..6) }

and this does pass the above test.

After finding this, I was trying to figure out why my original code didn't work, and so I thought that maybe Ruby was passing by reference, and that's why when the dice-rolling-method created a new array instead of modifying the existing array, that was a new object id created. But then I found this question, which says that Ruby is pass-by-value, and if that was the case, then I would have expected that my original way would work.

So now I'm confused again, and I'd like to ask - where did my line of thought go wrong? Is Ruby pass-by-value only in certain cases? Have I misunderstood what pass-by-value/reference even means? Is my issue not related to pass-by-value/reference at all?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
uppercase
  • 23
  • 3
  • 1
    It's a good question and you're on the right answer page but I think [this](https://stackoverflow.com/a/10974116/3109182) is a better explanation of what's happening. – Anthony Aug 18 '17 at 14:00

1 Answers1

0

You can see object in ruby as a reference to data. So even if Ruby is pass by value, the thing got copy is object, a.k.a a handle to underlining data.

Even from the answer you link to, had said:

Variables are always references to objects. In order to get an object that won't change out from under you, you need to dup or clone the object you're passed, thus giving an object that nobody else has a reference to. (Even this isn't bulletproof, though — both of the standard cloning methods do a shallow copy, so the instance variables of the clone still point to the same objects that the originals did. If the objects referenced by the ivars mutate, that will still show up in the copy, since it's referencing the same objects.)

xuanduc987
  • 1,067
  • 1
  • 9
  • 10