[Q] Array default values, << and <<=

Hi!

I’ve found a nice solution to have arrays and hashes a nice default
value, but I’m now confused.

Now, I use ruby 1.8

irb(main):004:0> b=Hash.new()
=> {}
irb(main):005:0> b[1] << 1
=> [1]
irb(main):006:0> b # Where is the one?
=> {}
irb(main):007:0> b[1] <<= 1
=> [1, 1]

So my confusion:
rb(main):001:0> a=[1,2]
=> [1, 2]
irb(main):002:0> a << 3
=> [1, 2, 3]
irb(main):003:0> a
=> [1, 2, 3]

So what << and <<= exactly do?
Gergo

···


±[ Kontra, Gergelykgergely@mcl.hu PhD student Room IB113 ]---------+

http://www.mcl.hu/~kgergely “Olyan langesz vagyok, hogy |
Mobil:(+36 20) 356 9656 ICQ: 175564914 poroltoval kellene jarnom” |
±–Magyar php mirror es magyar php dokumentacio: http://hu.php.net---+

I’ve found a nice solution to have arrays and hashes a nice default
value, but I’m now confused.

Now, I use ruby 1.8

irb(main):004:0> b=Hash.new()
=> {}

Some care needed there. Every non-existent key of b will return a reference
to the same array, not a new one (which might not be what you want,
especially if you change the array object)

Consider it like this:

obj =
b = Hash.new(obj)

irb(main):005:0> b[1] << 1
=> [1]
irb(main):006:0> b # Where is the one?
=> {}

b[1] references a non-existent entry so you get the array returned (i.e.
‘obj’ in my version). You then push a ‘1’ onto this array. However you do
not modify b in any way, you only modify obj.

So at this point:
b = {}
obj = [1]

irb(main):007:0> b[1] <<= 1
=> [1, 1]

This is short for:
b[1] = b[1] << 1

So what this does is:

b[1] # hash is empty so returns obj (which is now [1])
b[1] << 1 # pushes a 1 onto obj, so it’s now [1,1]
b[1] = … # assigns it to b[1]

This leaves b[1] = obj = [1,1]

Try ‘p b[2]’ and you’ll also get [1,1] because the same obj is returned for
a non-existent key. But:

b.has_key?(1) #>> true
b.has_key?(2) #>> false

So my confusion:
rb(main):001:0> a=[1,2]
=> [1, 2]
irb(main):002:0> a << 3
=> [1, 2, 3]
irb(main):003:0> a
=> [1, 2, 3]

So what << and <<= exactly do?

‘<<’ is an operator. For Array, by default it does the same as ‘push’ - adds
a value to the end of an array.

a <<= b is expanded internally to a = a << b

Now, this is probably not what you want or expect; you probably want a new
empty array every time you use a Hash key which does not exist in the Hash.
The usual way to get around this in Ruby is:

b[1] ||= []    # if b[1] does not exist, assign a new array to it
b[1] << 1      # now push something onto it

I think Ruby version 1.8 lets you do:

b = Hash.new { [] }

In this case, the block is executed each time a non-existent element is
accessed, so you get a new empty Array generated.

Regards,

Brian.

···

On Tue, Apr 15, 2003 at 02:51:49AM +0900, KONTRA Gergely wrote: