Skip to content

Instantly share code, notes, and snippets.

@teancom
Created May 2, 2013 04:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teancom/5500095 to your computer and use it in GitHub Desktop.
Save teancom/5500095 to your computer and use it in GitHub Desktop.
# This one works
class DiceSet
def roll(size)
@dice = []
size.times do |x|
@dice[x] = rand(1..6)
end
end
def values
@dice
end
end
vs
# This one doesn't (i.e., the test fails) - when run from within the koan test
# It totally works fine when run in irb
class DiceSet
def initialize
@dice = []
end
def roll(size)
size.times do |x|
@dice[x] = rand(1..6)
end
end
def values
@dice
end
end
def test_dice_values_should_change_between_rolls
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"
end
@teancom
Copy link
Author

teancom commented May 2, 2013

Proof that the "broken" one works just fine in IRB, when I do exactly what the test is doing:

irb(main):001:0> class DiceSet
irb(main):002:1>
irb(main):003:1* def initialize
irb(main):004:2> @dice = []
irb(main):005:2> end
irb(main):006:1>
irb(main):007:1* def roll(size)
irb(main):008:2> @dice.clear
irb(main):009:2> size.times do |x|
irb(main):010:3* @dice[x] = rand(1..6)
irb(main):011:3> end
irb(main):012:2> end
irb(main):013:1>
irb(main):014:1* def values
irb(main):015:2> @dice
irb(main):016:2> end
irb(main):017:1>
irb(main):018:1* end
=> nil
irb(main):019:0> dice=DiceSet.new
=> #<DiceSet:0x007fe2338c91d8 @dice=[]>
irb(main):020:0> dice.roll(5)
=> 5
irb(main):021:0> dice.values
=> [4, 2, 6, 5, 3]
irb(main):022:0> dice.roll(5)
=> 5
irb(main):023:0> dice.values
=> [3, 6, 1, 4, 6]
irb(main):024:0>

@fifteen3
Copy link

fifteen3 commented May 2, 2013

Ok this is my theory.

@dice = []

that creates a reference to a new Array Object

in the initialize method only one Array Object is created
and referenced by @dice.

So every time you call roll, it updates that Array Object and the @dice always refers the same Array Object
regardless of the contents of the array.

So then in the test, another reference is created to the same object using the variable first_time and then another
reference is created using the variable second_time.

so when dice.roll(5) is called before second_time is assigned the reference, the variable first_time's reference to the
same object is updated.

So it is the second dice.roll(5) that makes first_time and second_time the same value.

In the original code because @dice = [] each time in the roll method a new Array Object is assigned to @dice each time.

The result being that first_time and second_time don't reference the same Array Object.

@teancom
Copy link
Author

teancom commented May 2, 2013

That makes a ton of sense, Carlo. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment