From: "David A. Black" Date: 2004-11-05T23:05:36+09:00 Subject: Re: Cleaner way to do this? Hi -- On Fri, 5 Nov 2004, Mark Hubbart wrote: > Well, after some interesting sidetracked thoughts, I came up with this form: > > [1,2,3,4].do_first{|n| print n}.then_rest{|n| print ", ",n} > 1, 2, 3, 4 ==>[1, 2, 3, 4] > > Then this quickly hacked implementation, using singleton methods to > turn the first block into a proxy quasi-enumerable object. Hmmmm.... it's a bit of a stretch to "get" that the first call is going to return its own block (with or without modifications :-) There's no technical reason for it not to, but I think it's kind of unidiomatic. > module Enumerable > def do_first(&block) > class << block > def then_rest > first_done = nil > @enum.each do |arg| > yield arg if first_done > first_done ||= [self[arg]] > end > end > end > this = self > block.instance_eval{@enum = this} > block > end > end Don't forget that there's no Enumerable#[], so this would not work for all Enumerables. For what it's worth (maybe not much), here's another possible way to go about it: module M def do_both(b1, b2, n=1) current = b1 i = 1 each do |e| current.call(e) i += 1 current = b2 if i > n end end end arr = [1,2,3,4,5] .extend(M) arr.do_both(lambda {|x| print x }, lambda {|x| print ", #{x}" }) David -- David A. Black dblack@wobblini.net