[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Array and instance variable problem?

Maxime Guilbot

1/24/2007 10:35:00 AM

Look at the code below, I got strange results, I know that there is a
problem in the code but I can't find it. I expect to have an array like
this:

[[4, 4], [8, 1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024,
1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024, 1024]]

at the ouput of get_next_10...

Does someone has the idea?

Thanks a lot,
Maxime.

class Dummy
def initialize
@indexes = Array.new(2, 1)
end

def get_next
@indexes[0] = @indexes[0]*2
@indexes[1] = @indexes[1]*2

@indexes
end

def get_next_10
all = []
for i in 0..9
all << get_next
end
all
end
end
=> nil

d = Dummy.new
=> #<Dummy:0x33b198 @indexes=[1, 1]>

d.get_next_10
=> [[1024, 1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024,
1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024,
1024]]

d.get_next
=> [2048, 2048]

d.get_next
=> [4096, 4096]

--
Posted via http://www.ruby-....

7 Answers

Robert Klemme

1/24/2007 11:21:00 AM

0

On 24.01.2007 11:34, Maxime Guilbot wrote:
> Look at the code below, I got strange results, I know that there is a
> problem in the code but I can't find it. I expect to have an array like
> this:
>
> [[4, 4], [8, 1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024,
> 1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024, 1024]]
>
> at the ouput of get_next_10...
>
> Does someone has the idea?

Your problem is aliasing: you're reusing the same @indexes over and over
again.

> Thanks a lot,
> Maxime.
>
> class Dummy
> def initialize
> @indexes = Array.new(2, 1)
> end
>
> def get_next
> @indexes[0] = @indexes[0]*2
> @indexes[1] = @indexes[1]*2
>
> @indexes

Make that @indexes.dup or do get_next.dup in get_next_10.

> end
>
> def get_next_10
> all = []
> for i in 0..9
> all << get_next
> end
> all
> end
> end
> => nil
>
> d = Dummy.new
> => #<Dummy:0x33b198 @indexes=[1, 1]>
>
> d.get_next_10
> => [[1024, 1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024,
> 1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024, 1024], [1024,
> 1024]]
>
> d.get_next
> => [2048, 2048]
>
> d.get_next
> => [4096, 4096]

Kind regards

robert

WoNáDo

1/24/2007 11:34:00 AM

0

Maxime Guilbot schrieb:
> def get_next
> @indexes[0] = @indexes[0]*2
> @indexes[1] = @indexes[1]*2
>
> @indexes
> end

Use "@indexes.dup" istead of "@indexes" as the last Statement,...

> def get_next_10
> all = []
> for i in 0..9
> all << get_next
> end
> all
> end
> end

....or "all << get_next.dup" instead of "all << get_next".

In both cases you will end up with:


pp d.get_next_10

=>

[[2, 2],
[4, 4],
[8, 8],
[16, 16],
[32, 32],
[64, 64],
[128, 128],
[256, 256],
[512, 512],
[1024, 1024]]

The reason is, that you refer the same object in all Array positions othewise.

Wolfgang Nádasi-Donner

Maxime Guilbot

1/24/2007 11:54:00 AM

0

Thanks a lot for your answers, I got it :)

I guessed that it was that kind of problem...
but I still don't understand why it's working if @indexes is not an
Fixnum, not an Array..

Anyway, your answers solved my problem,
Thanks again,
Maxime.

--
Posted via http://www.ruby-....

WoNáDo

1/24/2007 1:16:00 PM

0

Maxime Guilbot schrieb:
> but I still don't understand why it's working ...

Take a look to the following example.

>>>>> Code >>>>>

require 'pp'
class Dummy
def initialize
@indexes = Array.new(2, 1)
end

def get_next
@indexes[0] = @indexes[0]*2
@indexes[1] = @indexes[1]*2

@indexes
end

def get_next_10
all = []
for i in 0..9
all << get_next
end
all
end

def show_id
puts @indexes.object_id
end
end
d = Dummy.new

x = d.get_next_10
puts '##### show contents #####'
pp x
puts '##### show @indexes-id #####'
d.show_id
puts '##### show ids of Array elements #####'
x.each{|e|puts e.object_id}

>>>>> Output >>>>>

##### show contents #####
[[1024, 1024],
[1024, 1024],
[1024, 1024],
[1024, 1024],
[1024, 1024],
[1024, 1024],
[1024, 1024],
[1024, 1024],
[1024, 1024],
[1024, 1024]]
##### show @indexes-id #####
24861230
##### show ids of Array elements #####
24861230
24861230
24861230
24861230
24861230
24861230
24861230
24861230
24861230
24861230

>>>>> EOE >>>>>

Your original program pushes always the same object into the final array (here
named "d", and it ist the object, "@indexes" refers to. As a temporary help
think in "Pointers", than it shoud be clear.

Wolfgang Nádasi-Donner

Maxime Guilbot

1/25/2007 3:01:00 AM

0

Wolfgang, Thanks a lot for your detailed answer.

What I meant in my second message, is that when @indexes is a FixNum
(not an Array).
This code is working as expected:

#!/usr/local/bin/ruby

require 'pp'
class Dummy
def initialize
@indexes = 1
end

def get_next
@indexes = @indexes*2

@indexes
end

def get_next_10
all = []
for i in 0..9
all << get_next
end
all
end

def show_id
puts @indexes.object_id
end
end
d = Dummy.new

x = d.get_next_10
puts '##### show contents #####'
pp x
puts '##### show @indexes-id #####'
d.show_id
puts '##### show ids of Array elements #####'
x.each{|e|puts e.object_id}





The output I got is:

##### show contents #####
[2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
##### show @indexes-id #####
2049
##### show ids of Array elements #####
5
9
17
33
65
129
257
513
1025
2049


I am curious about this result, why is it not the same behaviour?

It's also always the same @indexes which got into the array, right?

Thanks a lot for your patience!
Maxime.

--
Posted via http://www.ruby-....

WoNáDo

1/25/2007 12:00:00 PM

0

Maxime Guilbot schrieb:
> What I meant in my second message, is that when @indexes is a FixNum
> (not an Array).
> This code is working as expected:

In the code

def get_next
@indexes[0] = @indexes[0]*2
@indexes[1] = @indexes[1]*2

@indexes
end

the contents of "@indexes" will be changed, but the "Array" object will be the
same. In

def get_next
@indexes = @indexes*2

@indexes
end

"@indexes*2" will create a new object, which will be assigned to "@indexes"
afterwards.

Conclusion: in case of the Array object you will end with the same object with
changed contents (the same is valid for Hash objects, and may be valid for
strings - see below), in case of the Fixnum object a new object will be created
and referenced.

An example for class String to clarify this.

>>>>> Code >>>>>

require 'pp'
class Dummy
def initialize
@indexes = "a"
end

def get_next
@indexes[0,1] = @indexes[0,1].succ

@indexes
end

def get_next_10
all = []
for i in 0..9
all << get_next
end
all
end

def show_id
puts @indexes.object_id
end
end
d = Dummy.new

x = d.get_next_10
puts '##### show contents #####'
pp x
puts '##### show @indexes-id #####'
d.show_id
puts '##### show ids of Array elements #####'
x.each{|e|puts e.object_id}

>>>>> Output >>>>>

##### show contents #####
["k", "k", "k", "k", "k", "k", "k", "k", "k", "k"]
##### show @indexes-id #####
24861400
##### show ids of Array elements #####
24861400
24861400
24861400
24861400
24861400
24861400
24861400
24861400
24861400
24861400

>>>>> EoE >>>>>

If you change a line of code a little bit, something completely different will
happen.

>>>>> Parts of Code >>>>>

def get_next
# @indexes[0,1] = @indexes[0,1].succ
@indexes = @indexes.succ # <<<<<< Here is the minor change

@indexes
end

>>>>> Output >>>>>

##### show contents #####
["b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
##### show @indexes-id #####
24861380
##### show ids of Array elements #####
24861470
24861460
24861450
24861440
24861430
24861420
24861410
24861400
24861390
24861380

>>>>> EoE >>>>>

Wolfgang Nádasi-Donner

Maxime Guilbot

1/25/2007 2:06:00 PM

0

Thanks a lot Wolfgang, I completely understood!

Your explanation are great and very detailed, if I would have to score,
I would say 10/10 ;)

Bests regards,
Maxime.


--
Posted via http://www.ruby-....