mrcode / mediaone.net wrote:

> a = [(0..20), (43..150), ['z','yz','xyz','xz','zz']]
> cascade(a) do |width, length, hight|
>   puts "width is: #{width}, length is: #{length}, hight is: #{hight}"
> end
> 
> But overall I think Joel VanderWerf's Enumerable tools are probably better
> thought out and implemented than my version.  I'll probably be adding that
> to my list of useful libraries.

There's something a little different about the product operator I
defined. It returns a new "proxy" enumerable which delegates to the
given ones (the factors of the product). So, in the current version
(**), you can't just pass a block to it, you have to call each on the
return value of product:

  require 'enum/op'
  include EnumerableOperator

  a = [(0..20), (43..150), ['z','yz','xyz','xz','zz']]
  product(*a).each do |width, length, hight|
    puts "width is: #{width}, length is: #{length}, hight is: #{hight}"
  end

However, this allows use of 'for', which is very readable:

  for width, length, hight in product(*a)
    puts "width is: #{width}, length is: #{length}, hight is: #{hight}"
  end

Also, you can chain with other iterations without generating the
intermediate collection, which may be large:

  product(*a).select { |w, l, h| w > 18 && l < 45 && h == 'zz' }

----
(**) With a small change, you can pass a block and have product behave
like cascade. Just define product as follows:

  def product(*factors, &block)
    if block
      Product.new(*factors).each &block
    else
      Product.new(*factors)
    end
  end

Now you can leave out the ".each":

  product(*a) do |width, length, hight|
    puts "width is: #{width}, length is: #{length}, hight is: #{hight}"
  end

This'll go in the next version.

--
Joel VanderWerf                          California PATH, UC Berkeley
mailto:vjoel / path.berkeley.edu                     Ph. (510) 231-9446
http://www.path.berkeley.edu                       FAX (510) 231-9512