From: Ben Tilly Date: 2001-01-09T20:52:14+09:00 Subject: [ruby-talk:8917] Re: Modules and mixins "Christoph Rippel" wrote: > > > -----Original Message----- > > From: Ben Tilly [mailto:ben_tilly@hotmail.com] > > Sent: Monday, January 08, 2001 08:26 PM > > To: ruby-talk ML > > Subject: [ruby-talk:8897] Re: Modules and mixins >... > > If length is the primary issue (yes, I renamed the method): > >The length was not the issue on the python ml. The original author of the >MRange >class - he called it the ``Dice class '' if I remember correctly - just >wanted to >demonstrate that the block & closure implementation are definite highlights >of ruby. >I was a little amused about a response on the python ml, arguing that a >rather >beautiful but also long winded iterator implementation which explicitly >calculates >the position of an individual element is a conceptually superior solution. >Even so >``block iterators'' probably take a while to get used to they are >preferable over >the ``position math'' of something like ... > Say no more. Explicit calculations open up room for all sorts of potential mistakes. > >class Combs > def initialize(m,n,p=1) > raise ArgumentError if m - n < p > @m = m > @n = n > @p = p > end > def each > __e(@m,@n) { |l| yield l } > end >private > def __e(i,j) > if j <= @p > i.downto (1) { |l| yield [l] } > else > i.downto (j) \ > { |l| __e(l-@p,j-@p) { |r| yield [l]+r }} > end > end >end > >Combs.new (8, 5, 2).each \ >{| l| puts l.join " "} > > >The implementation of the original Dice version was actually closer to your >solution >and if you throw in your argument separation trick Not much of a trick. I just intended to use argument processsing to do what would otherwise be mechanical in my original Perl version. > >def bind_loops(fn, my_range, *more_args) > ^^^^^^^^^^^ >... > > bind_loops(bound_fn, *more_args) : > ^^^^^^^^ > >end > >could be rewritten in a rather compact form > >def each (arg,*more_args) > ( [] != args ) ? > arg.each {|l| each(*more_args) {|r| yield [l]+ r }} : > arg.each { |r| yield [r] } >end > >each( 1..2, 'a'..'c', 'A'..'D') \ >{ |args| puts args.join " " } > Huh. This is what I said I had not played with. Looking at this "feels" like an inside-out twist on my solution. I think I like the pattern of this one better, just a tad more direct. However I would prefer different names: def each_comb (arg,*more_args) ( [] != more_args ) ? arg.each {|l| each_comb(*more_args) {|r| yield [l]+ r }} : arg.each { |r| yield [r] } end each_comb( 1..2, 'a'..'c', 'A'..'D') \ { |args| puts args.join " " } Why? Because to me "each" is an already well-defined concept and each combination doesn't not seem to me to be at all the same. So the subtly different names make that intent a lot clearer. (Well for me at least.) Cheers, Ben _________________________________________________________________ Get your FREE download of MSN Explorer at http://explorer.msn.com