From: Brian Candler Date: 2004-11-05T18:18:58+09:00 Subject: Re: Cleaner way to do this? > > If your friend knows the processing he wants to do on the first > > element, why not just keep it simple... > > > arr = [1,2,3,4,5] > > process = proc{ |e| print e }.call( arr[0] ) > > arr[1...arr.length].each do |e| > > print ", #{e}" > > end > > Agreed :-). > > I think the original discussion came about because he was interested in > iterators and wanted to understand how one might write an efficient > iterator that allowed for handling of special cases, like doing > something different with the first or last entry in a collection. > > I didn't like to dampen that kind of enthusiasm. A generic solution, which works on anything enumerable (such as lines of a File) will not use foo.length, because the number of items isn't necessarily known at the start. Here's one way to avoid the test each time round the loop: module Enumerable def each_except_first(first=nil, &rest) iter = proc { |e| first.call(e) if first; iter = rest } each { |e| iter.call(e) } end end #a = File.open("/etc/motd") a = ["one", "two", "three"] a.each_except_first(proc { |e| print e }) { |e| print ", #{e}" } However this still involves an extra level of block call. It's a shame there's not a Proc#replace method, otherwise you could write something like module Enumerable def each_except_first(first=nil, &rest) iter = proc { |e| first.call(e) if first; iter.replace(rest) } each &iter end end Regards, Brian.