> -----Original Message-----
> From: Ben Tilly [mailto:ben_tilly / hotmail.com]
> Sent: Sunday, January 07, 2001 06:25 PM
> To: ruby-talk ML
> Subject: [ruby-talk:8803] Re: Modules and mixins
> 
> 
> Ruby also supports functional techniques.  You call proc()
> to produce a procedure, and then call it many times.  The
> following quick hack shows what those techniques look like,
> though it is a port of a quick example I did in Perl and I
> don't know if it is how you would want to solve this problem
> in Ruby:
> 
>   #! /usr/local/bin/ruby -w
> 
>   def nested_for (fn, *arg)
>     bind_param(fn, *arg)[]
>   end
> 
>   def bind_param(fn, my_range, *more_args)
>     bound_fn = proc { |*args|
>       for arg in my_range do
>         fn[arg, *args]
>       end
>     }
>     (0 == more_args.length()) ?
>       bound_fn :
>       bind_param(bound_fn, *more_args)
>   end
> 
>   nested_for \
>     proc  {|*arg| puts arg.join(" ")} , \
>     1..2, 'a'..'c', 'A'..'D'
>
Yes, this is a very need solution!

Interestingly enough (basically) the same example came up
in a very long ``Ruby versus Python'' thread on the python 
list in the middle of November 2000. The proposed Ruby 
solution was something along the line of: 

class  MRange
   def initialize (*a)
      @len  = a.length/2 -1
      @lo = a[0.. / len]
      @up = a[@len+1..2*@len+1]
   end
   def each
      __each(0) {|l| yield l }
   end
   private	
   def __each(n)
      if n == @len
        (@lo[n]..@up[n]).each { |l| yield [l] }
      else	
         (@lo[n]..@up[n]).each \
          { |l|  __each(n+1) {|r| yield [l]+ r }}
      end	
   end	
end

MRange.new(1,'a','A', 2,'c','D').each \
{|arg| puts arg.join(" ")}   


The elegance (? probably a matter of taste) of this Ruby 
solution was dismissed since it is pretty easy to calculate
the index of an element in a ``Multi-Range'' directly.
(Nobody was public disconcerted that this ``elegant
solution'' was probably 3 or 4  times as long).

Christoph