Nested Arrays in Method Definitions--a puzzle

Hello there Ruby-minded people!

 I am writing because I am somewhat stumped by why the following

discrepency occurs; having defined the following:

class Warfare
def haves
x = [1]
y = []
y << x
x = [2] # (compare this)
def havenots
x = [1]
y = []
y << x
x[0] = 2 # (to this)

I get this in irb:

load ‘snah.rb’
=> true

a =
=> #Warfare:0x33a93c

=> [[1]]

=> [[2]]

Why does meddling with the innards of the “x” have retroactive
repercussions, whereas redefining it outright does not?

Any insight would be greatly appreciated.


On Tue, Aug 19, 2008 at 4:16 PM, Jonah Bloch-Johnson
[email protected] wrote:

repercussions, whereas redefining it outright does not?
When you say ‘x = [2]’ you aren’t redefining the object x, you are
taking the variable ‘x’ and binding it to a new object. When you say y
<< x, you are inserting the object that x was pointing to at that
moment into y, not the variable x. Think of a variable as an alias for
an object - what is actually passed around are the objects themselves,
but you can refer to them by any of their current aliases.


Many many many thanks, Adam and Martin! I do think this clears it up.

Quoting A. Shelly [email protected]:

On 8/19/08, Jonah Bloch-Johnson [email protected] wrote:

I am writing because I am somewhat stumped by why the following discrepency occurs…

Variables and Array entries hold references to objects.

irb(main):001:0> x=[1]
=> [1]
irb(main):002:0> x.object_id
=> 20774910

irb(main):003:0> y=[];y<<x
=> [[1]]
irb(main):004:0> y[0].object_id
=> 20774910 #the same object that x referrs to

irb(main):005:0> x=[2]
=> [2]
irb(main):006:0> x.object_id
=> 21222360 #now x refers to the newly created array

irb(main):008:0> y
=> [[1]]
irb(main):007:0> y[0].object_id
=> 20774910 #but y still holds a reference to the old one.

irb(main):009:0> y=[x]
=> [[2]]
irb(main):010:0> y[0].object_id
=> 21222360 #y[0] is now a reference to the same Array as x

irb(main):011:0> x[0]=4
=> 4
irb(main):013:0> y
=> [[4]] #so changes to the content of that Array are visible
through y’s reference.

hope this helps,

   x = [1]

[1] is an Array object, x is a variable referring to that array

   y = []

y referrs to a 2nd Array

   y << x

And now that array contains a reference to

   x = [2] # (compare this)

Here you are creating an array, labeling it ‘x’, and storing a
reference to it in the array labeled y. Then you reassign the ‘x’
label to yet another array (the one containing 2).

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs