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: