> -----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 ...


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

>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 " " }


Christoph