Forum: Ruby Array and instance variable problem?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
6719a2ee05da4c03415c86200d84eaab?d=identicon&s=25 Maxime Guilbot (maximeg)
on 2007-01-24 11:34
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]
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-01-24 12:25
(Received via mailing list)
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.

>     @indexes[1] = @indexes[1]*2
>
>     @indexes

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

> => nil
> => [2048, 2048]
>
> d.get_next
> => [4096, 4096]

Kind regards

  robert
A131b672fdbd2a58dce12031ad78b121?d=identicon&s=25 Wolfgang Nádasi-Donner (wonado)
on 2007-01-24 12:35
(Received via mailing list)
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
6719a2ee05da4c03415c86200d84eaab?d=identicon&s=25 Maxime Guilbot (maximeg)
on 2007-01-24 12:53
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.
A131b672fdbd2a58dce12031ad78b121?d=identicon&s=25 Wolfgang Nádasi-Donner (wonado)
on 2007-01-24 14:15
(Received via mailing list)
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
6719a2ee05da4c03415c86200d84eaab?d=identicon&s=25 Maxime Guilbot (maximeg)
on 2007-01-25 04:00
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.
A131b672fdbd2a58dce12031ad78b121?d=identicon&s=25 Wolfgang Nádasi-Donner (wonado)
on 2007-01-25 13:00
(Received via mailing list)
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
6719a2ee05da4c03415c86200d84eaab?d=identicon&s=25 Maxime Guilbot (maximeg)
on 2007-01-25 15:05
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.
This topic is locked and can not be replied to.