On 14.01.2007 12:49, karthik wrote:
wow, robert, that makes a lot of sense Thanks !
You’re welcome!
now my next question: how would a newbie (like me) know by looking at
the ruby doc that Array.map could actually support 2D arrays in this
fashion?
(or is it that it just becomes “obvious” as one uses Ruby more and
more?!)
I guess the latter. What you see is basically the effect of a
combination of features: You’re actually not dealing with a 2D Array but
with an Array that contains Arrays, or more generally, an Enumerable
that contains Enumerables. A true 2D Array would make sure that every
row has the same number of elements and similarly for columns, that’s
why it’s not a 2D Array. The other aspect is how yield and assignments
work. There is some automatic, err, how would you call that, unrolling?
irb(main):001:0> a,b=1,2
=> [1, 2]
irb(main):002:0> a
=> 1
irb(main):003:0> b
=> 2
irb(main):004:0> a,b=[1,2]
=> [1, 2]
irb(main):005:0> a
=> 1
irb(main):006:0> b
=> 2
So, an Array is automatically assigned element wise you do not need to
explicitly provide the splat operator:
irb(main):007:0> a,b=*[1,2]
=> [1, 2]
irb(main):008:0> a
=> 1
irb(main):009:0> b
=> 2
You can do a lot more fancy stuff with this as Ruby actually does
pattern matching:
irb(main):001:0> a,b,c=1,[2,3]
=> [1, [2, 3]]
irb(main):002:0> a
=> 1
irb(main):003:0> b
=> [2, 3]
irb(main):004:0> c
=> nil
irb(main):005:0> a,(b,c)=1,[2,3]
=> [1, [2, 3]]
irb(main):006:0> a
=> 1
irb(main):007:0> b
=> 2
irb(main):008:0> c
=> 3
This is often useful when using #inject on a Hash:
$ irb
irb(main):001:0> h={}
=> {}
irb(main):002:0> 10.times { i=rand(10); h[i]=10-i}
=> 10
irb(main):003:0> h
=> {0=>10, 6=>4, 7=>3, 2=>8, 8=>2, 3=>7, 9=>1, 4=>6}
irb(main):004:0> h.size
=> 8
irb(main):005:0> h.inject(0) {|sum,(key,val)| sum + key + val}
=> 80
This is of course a silly example. I chose these values in order to
make checking what’s going on easier (i.e. summing all keys and values
equals h.size * 10).
Kind regards
robert