Robert Klemme
1/14/2007 12:41:00 PM
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