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