From: Robert Klemme Date: 2008-09-15T21:17:06+09:00 Subject: Re: Redefe each to include each_with_index and arity=2 2008/9/12 DanDiebolt.exe : > Thanks for pointing this out. I have two motivations to pursue this: > > 1) I am interested in more deeply learning all of ruby language constructs but I only occasionally write my own classes & iterators. I would like to get the the point where I can do this with ease. > > 2) As a practical matter I often have to modify code I wrote a while ago that was originally thrown together for a quick solution to a one of a kind problem. So I like to use editing techniques that can quickly modify code without of a lot of rework. It may seem trivial, but is sure seems to me that adding an index parameter to the each iterator is a lot easier than changing the method to each_with_index AND adding an index parameter. In other words, moving from this code: > > a.each do |item| > #process item > end > > to this code: > > a.each do |item,index| > #process item & index > end > > is easier to remember and edit than using this code: > > a.each_with_index do |item,index| > > #process item & index > > end > > So if Ruby is such a great dynamic language and DSL (I know it is!) there should be a straightforward way to accomplish this despite the *args problem you mention. > > So does anyone know how each could be expanded in this fashion to work for all enumerable types (ranges, hashes, sets ...)? I'd rather discourage doing this. If you edit source code to add another block parameter then it seems equally easy to replace "each" with "each_with_index". Note that evaluating the arity of the block has some issues because for a Hash you usually provide two arguments as in a_hash.each do |key, value| # arity 2 print key, " ---> ", value, "\n" end or one argument as in a_hash.each do |*pair| # arity -1 p pair end And even to an each_with_index for a Hash you can reasonably provide two (!) arguments: irb(main):007:0> def ar(&b) b.arity end => nil irb(main):008:0> {"a"=>"b"}.each_with_index {|(k,v),i| p k,v,i} "a" "b" 0 => {"a"=>"b"} irb(main):009:0> ar {|(k,v),i| p k,v,i} => 2 Kind regards robert -- use.inject do |as, often| as.you_can - without end