From: Jano Svitok Date: 2008-02-07T11:51:00+09:00 Subject: Re: info on block arguments On Feb 7, 2008 3:25 AM, Russell Me wrote: > I'm trying to pick up ruby and I'm impressed by all the cool stuff it > does out of the box. I'm reading a few books but i'm finding why's > poignant guide to ruby to be the most helpful and entertaining > (http://poignantguide.net/ruby). > > However, I'm a bit stuck understanding how block arguments work. in his > example: > > kitty_toys = [ > {:shape => 'sock', :fabric => 'cashmere'}, > {:shape => 'mouse', :fabric => 'calico'}, > {:shape => 'eggroll', :fabric => 'chenille'} > ] > > kitty_toys.sort_by { |toy| toy[:shape] }.each do |toy| > puts "Blixy has a #{ toy[:shape] } made of #{ toy[:fabric] }" > end > > I know what it does. I put it through irb and it works. But i don't > understand HOW it works, exactly. Mainly, the toy bit. I don't quite get > what role it plays in the code and how the code uses it. > > I've read up online and in both books I have, but, for whatever reason i > STILL cannot grasp block arguments and what role they play. > > Maybe I'm just brain farting here, but if anyone could lend some tips on > this I'd appreciate it. As you may know, "toy" is the argument to block. Block is a special form of function, and using this |argument| the function sort_by passes data to the block. It makes more sense if you put yield in the picture as well. Let's see how e.g. upto is implemented: class Integer def upto_(limit) counter = self while counter <= limit yield counter counter += 1 end end end In other words: we do something, and in special places we call the block function (yield). We pass the counter as the block argument. Now we can try the outer view of this thing -- we'll see the block being called with various numbers: 10.upto_(20) { |counter| puts counter } And back to your/_why's example: it's a chain of several method calls: 1. we call sort_by with { |toy| toy[:shape] } block on kitty_toys 2. then we call each with do ... end block on the result of step 1. sort_by uses the block to generate sort index for each item in the array. The block gets an item, and returns the index for that item. (in this case, we want to sort_by toy's :shape) sort_by returns sorted array. Then we call each on the result array. each calls the block with each item one by one. So, the do...end block gets called 3 times, once for each item. That block just prints the item, as you have noticed. So, this is my attempt to explain. If it doesn't make sense, maybe it's because it's 4 AM here ;-) Jano