Nested Arrays in Method Definitions--a puzzle

  • Thread starter Jonah Bloch-Johnson
  • Start date
J

Jonah Bloch-Johnson

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)
y
end
def havenots
x = [1]
y = []
y << x
x[0] = 2 # (to this)
y
end
end

I get this in irb:
load 'snah.rb' => true
a = Warfare.new
=> # said:
a.haves => [[1]]
a.havenots
=> [[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.

-Jonah
 
M

Martin DeMello

def haves
x = [1]
y = []
y << x
x = [2] # (compare this)
y
end

Why does meddling with the innards of the "x" have retroactive
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.

martin
 
A

Adam Shelly

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,
-Adam



























































[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).
end
def havenots
x = [1]
y = []
y << x
x[0] = 2 # (to this)
y
end
end

I get this in irb:
=> # said:
=> [[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.

-Jonah
 
J

Jonah Bloch-Johnson

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

Quoting Adam Shelly said:
I am writing because I am somewhat stumped by why the following =20
discrepency occurs...

Variables and Array entries hold references to objects.

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

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

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

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

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

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


hope this helps,
-Adam


























































x =3D [1]

[1] is an Array object, x is a variable referring to that array
y =3D [] y referrs to a 2nd Array
y << x

And now that array contains a reference to
x =3D [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).
end
def havenots
x =3D [1]
y =3D []
y << x
x[0] =3D 2 # (to this)
y
end
end

I get this in irb:
load 'snah.rb'

=3D> true

a =3D Warfare.new
=3D> # said:
a.haves

=3D> [[1]]

a.havenots
=3D> [[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.

-Jonah
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top