From: Mark Hubbart Date: 2004-11-06T04:39:52+09:00 Subject: Re: Cleaner way to do this? Hi, On Fri, 5 Nov 2004 23:05:36 +0900, David A. Black wrote: > 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. I'm not claiming this is good code - I know it's not. But it was fun to write :) I think it shows how flexible Ruby is. The end syntax is very readable, though the method chaining isn't. And the method names leave something to be desired. > > 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. I didn't use Enumerable#[] "one\ntwo\nthree".do_first{|n| print n.chomp}.then_rest{|n| print ", ",n.chomp} one, two, three ==>"one\ntwo\nthree" (1..3).do_first{|n| print n}.then_rest{|n| print ", ",n} 1, 2, 3 ==>1..3 I did use #[] on a block... > 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}" }) The challenge I took was to figure out a way to pass two blocks, without lambda/proc/Proc.new. I did that by using method chaining and a proxy object. I agree that the idea wasn't worth much, except maybe as an exercise. And I'm not suggesting the OP show this to his friend :) Anyway, please forgive my ugly code :) I'll leave this now... cheers, Mark > > David > > -- > David A. Black > dblack@wobblini.net > >